diff --git a/lib/lib-storage/src/Upload.spec.ts b/lib/lib-storage/src/Upload.spec.ts index 9d63f064b38ea..a92fcb1c612bb 100644 --- a/lib/lib-storage/src/Upload.spec.ts +++ b/lib/lib-storage/src/Upload.spec.ts @@ -296,6 +296,22 @@ describe(Upload.name, () => { expect(result.Location).toEqual("https://s3.region.amazonaws.com/example-bucket/example-key"); }); + it("should return a Location field with decoded slash symbols", async () => { + const partSize = 1024 * 1024 * 5; + const largeBuffer = Buffer.from("#".repeat(partSize + 10)); + const actionParams = { ...params, Body: largeBuffer }; + const completeMultipartMockWithLocation = completeMultipartMock.mockResolvedValueOnce({ + Location: "https://example-bucket.example-host.com/folder%2Fexample-key", + }); + const upload = new Upload({ + params: actionParams, + client: new S3({}), + }); + const result = (await upload.done()) as CompleteMultipartUploadCommandOutput; + expect(completeMultipartMockWithLocation).toHaveBeenCalledTimes(1); + expect(result.Location).toEqual("https://example-bucket.example-host.com/folder/example-key"); + }); + it("should upload using multi-part when parts are larger than part size", async () => { // create a string that's larger than 5MB. const partSize = 1024 * 1024 * 5; diff --git a/lib/lib-storage/src/Upload.ts b/lib/lib-storage/src/Upload.ts index f7499911788ac..78538d529b8cc 100644 --- a/lib/lib-storage/src/Upload.ts +++ b/lib/lib-storage/src/Upload.ts @@ -334,6 +334,9 @@ export class Upload extends EventEmitter { }, }; result = await this.client.send(new CompleteMultipartUploadCommand(uploadCompleteParams)); + if (typeof result?.Location === "string" && result.Location.includes("%2F")) { + result.Location = result.Location.replace(/%2F/g, "/"); + } } else { result = this.singleUploadResult!; }