diff --git a/packages/abstractions/src/multipartBody.ts b/packages/abstractions/src/multipartBody.ts index f3e940cbd..89f8611de 100644 --- a/packages/abstractions/src/multipartBody.ts +++ b/packages/abstractions/src/multipartBody.ts @@ -27,8 +27,9 @@ export class MultipartBody implements Parsable { * @param partContentType the content type of the part to add or replace. * @param content the content of the part to add or replace. * @param serializationCallback the serialization callback to use when serializing the part. + * @param fileName the name of the file associated with this part. */ - public addOrReplacePart(partName: string, partContentType: string, content: T, serializationCallback?: ModelSerializerFunction): void { + public addOrReplacePart(partName: string, partContentType: string, content: T, serializationCallback?: ModelSerializerFunction, fileName?: string): void { if (!partName) throw new Error("partName cannot be undefined"); if (!partContentType) { throw new Error("partContentType cannot be undefined"); @@ -39,6 +40,7 @@ export class MultipartBody implements Parsable { contentType: partContentType, content, originalName: partName, + fileName, serializationCallback, }; } @@ -90,6 +92,7 @@ interface MultipartEntry { contentType: string; content: any; originalName: string; + fileName?: string; serializationCallback?: ModelSerializerFunction; } @@ -124,7 +127,7 @@ export const serializeMultipartBody = (writer: SerializationWriter, multipartBod const part = parts[partName]; writer.writeStringValue("Content-Type", part.contentType); writer.writeStringValue(undefined, "\r\n"); - writer.writeStringValue("Content-Disposition", 'form-data; name="' + part.originalName + '"'); + writer.writeStringValue("Content-Disposition", `form-data; name="${part.originalName}"${part.fileName ? `; filename="${part.fileName}"` : ""}`); writer.writeStringValue(undefined, "\r\n"); writer.writeStringValue(undefined, "\r\n"); if (typeof part.content === "string") { diff --git a/packages/abstractions/test/common/multipartBody.ts b/packages/abstractions/test/common/multipartBody.ts index e3c1b063a..842cb14b9 100644 --- a/packages/abstractions/test/common/multipartBody.ts +++ b/packages/abstractions/test/common/multipartBody.ts @@ -40,3 +40,31 @@ describe("multipartBody", () => { }); //serialize method is tested in the serialization library }); + +describe("multipartBody with fileName", () => { + const arrayBuffer = new Uint8Array([0x01, 0x01, 0x01]); + const arrayBuffer2 = new Uint8Array([0x02, 0x02, 0x02]); + + it("adds parts with a filename", () => { + const mpBody = new MultipartBody(); + mpBody.addOrReplacePart("filepart", "application/octet-stream", arrayBuffer, undefined, "file.txt"); + + const part = mpBody.listParts()["filepart"]; + assert.exists(part); + assert.strictEqual(part.contentType, "application/octet-stream"); + assert.strictEqual(part.content, arrayBuffer); + assert.strictEqual(part.fileName, "file.txt"); + }); + + it("updates filename when replacing a part", () => { + const mpBody = new MultipartBody(); + mpBody.addOrReplacePart("filepart", "application/octet-stream", arrayBuffer, undefined, "file.txt"); + mpBody.addOrReplacePart("filepart", "application/pdf", arrayBuffer2, undefined, "document.pdf"); + + const part = mpBody.listParts()["filepart"]; + assert.exists(part); + assert.strictEqual(part.fileName, "document.pdf"); + assert.strictEqual(part.content, arrayBuffer2); + assert.strictEqual(part.contentType, "application/pdf"); + }); +}); diff --git a/packages/serialization/multipart/test/common/multipartSerializationWriter.ts b/packages/serialization/multipart/test/common/multipartSerializationWriter.ts index 810a0b069..ff379d7c8 100644 --- a/packages/serialization/multipart/test/common/multipartSerializationWriter.ts +++ b/packages/serialization/multipart/test/common/multipartSerializationWriter.ts @@ -122,4 +122,17 @@ describe("MultipartSerializationWriter", () => { const multipartSerializationWriter = new MultipartSerializationWriter(); assert.throw(() => multipartSerializationWriter.writeCollectionOfObjectValues(undefined, [testEntity])); }); + + it("serializes Content-Disposition with filename", () => { + const mpBody = new MultipartBody(); + mpBody.addOrReplacePart("file", "application/octet-stream", byteForTest, undefined, "file.txt"); + + const multipartSerializationWriter = new MultipartSerializationWriter(); + multipartSerializationWriter.writeObjectValue(undefined, mpBody, serializeMultipartBody); + const multipartContent = multipartSerializationWriter.getSerializedContent(); + const result = new TextDecoder().decode(multipartContent); + + const expectedString = "--" + mpBody.getBoundary() + '\r\nContent-Type: application/octet-stream\r\nContent-Disposition: form-data; name="file"; filename="file.txt"\r\n\r\n' + new TextDecoder().decode(byteForTest) + "\r\n--" + mpBody.getBoundary() + "--\r\n"; + assert.equal(result, expectedString); + }); });