diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 3b4cc6ce59c2..6cf72b742aa9 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -1,7 +1,8 @@ # Release History ## 12.8.0-beta.2 (Unreleased) - +- Fixed a bug that, when the data length parameter did not match the actual length of the data in BlobClient.upload, caused a zero length blob to be uploaded rather than throwing an exception. +- Fixed a bug that ignored the customer's specified block size when determining buffer sizes in BlobClient.upload ## 12.8.0-beta.1 (2020-07-07) - Added support for the 2019-12-12 service version. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index 6548b3a8824d..7410eac63e0a 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -439,7 +439,9 @@ public Mono> uploadWithResponse(BlobParallelUploadOption .setTier(options.getTier()).setRequestConditions(options.getRequestConditions())); Flux data = options.getDataFlux() == null ? Utility.convertStreamToByteBuffer( - options.getDataStream(), options.getLength(), BLOB_DEFAULT_UPLOAD_BLOCK_SIZE) + options.getDataStream(), options.getLength(), + // We can only buffer up to max int due to restrictions in ByteBuffer. + (int) Math.min(Integer.MAX_VALUE, validatedParallelTransferOptions.getBlockSizeLong())) : options.getDataFlux(); return UploadUtils.uploadFullOrChunked(data, ModelHelper.wrapBlobOptions(validatedParallelTransferOptions), uploadInChunksFunction, uploadFullBlobMethod); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy index e0443ee9fb69..669564ca2640 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy @@ -85,8 +85,9 @@ class BlobAPITest extends APISpec { } /* Tests an issue found where buffered upload would not deep copy buffers while determining what upload path to take. */ + @Unroll - def "Upload input stream single upload" () { + def "Upload input stream single upload"() { setup: def randomData = getRandomByteArray(20 * Constants.KB) def input = new ByteArrayInputStream(randomData) @@ -100,15 +101,15 @@ class BlobAPITest extends APISpec { stream.toByteArray() == randomData where: - size || _ - 1 * Constants.KB || _ /* Less than copyToOutputStream buffer size, Less than maxSingleUploadSize */ - 8 * Constants.KB || _ /* Equal to copyToOutputStream buffer size, Less than maxSingleUploadSize */ - 20 * Constants.KB || _ /* Greater than copyToOutputStream buffer size, Less than maxSingleUploadSize */ + size || _ + 1 * Constants.KB || _ /* Less than copyToOutputStream buffer size, Less than maxSingleUploadSize */ + 8 * Constants.KB || _ /* Equal to copyToOutputStream buffer size, Less than maxSingleUploadSize */ + 20 * Constants.KB || _ /* Greater than copyToOutputStream buffer size, Less than maxSingleUploadSize */ } /* TODO (gapra): Add more tests to test large data sizes. */ - @Requires( { liveMode() } ) + @Requires({ liveMode() }) def "Upload input stream large data"() { setup: def randomData = getRandomByteArray(20 * Constants.MB) @@ -124,6 +125,22 @@ class BlobAPITest extends APISpec { notThrown(BlobStorageException) } + @Unroll + def "Upload incorrect size"() { + when: + bc.upload(defaultInputStream.get(), dataSize, true) + + then: + thrown(IllegalStateException) + + where: + dataSize | threshold + defaultDataSize + 1 | null + defaultDataSize - 1 | null + defaultDataSize + 1 | 1 // Test the chunked case as well + defaultDataSize - 1 | 1 + } + @Unroll def "Upload numBlocks"() { setup: @@ -156,7 +173,8 @@ class BlobAPITest extends APISpec { .getValue().getETag() != null } - @Requires({ liveMode() }) // Reading from recordings will not allow for the timing of the test to work correctly. + @Requires({ liveMode() }) + // Reading from recordings will not allow for the timing of the test to work correctly. def "Upload timeout"() { setup: def size = 1024 @@ -973,7 +991,8 @@ class BlobAPITest extends APISpec { This test requires two accounts that are configured in a very specific way. It is not feasible to setup that relationship programmatically, so we have recorded a successful interaction and only test recordings. */ - @Requires( {playbackMode()}) + + @Requires({ playbackMode() }) def "Get properties ORS"() { setup: def sourceBlob = primaryBlobServiceClient.getBlobContainerClient("test1") diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[0].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[0].json new file mode 100644 index 000000000000..4ad94f6f9120 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[0].json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize61a372717?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "6bf35f33-b5b3-409c-8dc2-5f130fb97710" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D82819FF1A5384", + "Last-Modified" : "Tue, 14 Jul 2020 17:18:59 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "d46d6efa-901e-0054-2b02-5abe5e000000", + "Date" : "Tue, 14 Jul 2020 17:18:59 GMT", + "x-ms-client-request-id" : "6bf35f33-b5b3-409c-8dc2-5f130fb97710" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize61a372717/javablobuploadincorrectsize192960ae99c1dbb885442", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0addb259-10d1-4120-888b-ca7ae000dbb7", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "6RYQPwaVsyQ=", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:00 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 14 Jul 2020 17:18:59 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==", + "ETag" : "0x8D82819FFBE88FD", + "Content-Length" : "0", + "x-ms-request-id" : "b2e2badf-b01e-0061-7402-5a100b000000", + "x-ms-client-request-id" : "0addb259-10d1-4120-888b-ca7ae000dbb7" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcuploadincorrectsize&comp=list", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "3062524d-62b2-4ecf-8aa6-b0466c650321" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "3bcebc16-c01e-006e-3e02-5afdfd000000", + "Body" : "jtcuploadincorrectsizejtcuploadincorrectsize0blobapitestuploadincorrectsize61a372717Tue, 14 Jul 2020 17:18:59 GMT\"0x8D82819FF1A5384\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 14 Jul 2020 17:19:00 GMT", + "x-ms-client-request-id" : "3062524d-62b2-4ecf-8aa6-b0466c650321", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize61a372717?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "bf4ee0d9-d744-4434-86cd-d42dae8ef27a" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "8f04ebd6-801e-0040-0402-5a7d3a000000", + "Date" : "Tue, 14 Jul 2020 17:19:01 GMT", + "x-ms-client-request-id" : "bf4ee0d9-d744-4434-86cd-d42dae8ef27a" + }, + "Exception" : null + } ], + "variables" : [ "jtcuploadincorrectsize0blobapitestuploadincorrectsize61a372717", "javablobuploadincorrectsize192960ae99c1dbb885442" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[1].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[1].json new file mode 100644 index 000000000000..37e09ec0556d --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[1].json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizec47250537?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "3357dd18-4743-45cc-8c81-678638cd39d0" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D8281A00C3DE5B", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:02 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "4e84195f-e01e-009c-5b02-5a2f69000000", + "Date" : "Tue, 14 Jul 2020 17:19:01 GMT", + "x-ms-client-request-id" : "3357dd18-4743-45cc-8c81-678638cd39d0" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizec47250537/javablobuploadincorrectsize105800ad666ed1358e41c", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "b65064d9-44e9-4637-8afc-f1c27f9f1a99", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "6RYQPwaVsyQ=", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:02 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 14 Jul 2020 17:19:01 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==", + "ETag" : "0x8D8281A00F2D3DC", + "Content-Length" : "0", + "x-ms-request-id" : "b9dba07a-101e-000a-1102-5a4d5d000000", + "x-ms-client-request-id" : "b65064d9-44e9-4637-8afc-f1c27f9f1a99" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcuploadincorrectsize&comp=list", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "039695a3-cdd6-4f4f-bf61-0607b7441c14" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "919d11bb-201e-002b-5202-5a206c000000", + "Body" : "jtcuploadincorrectsizejtcuploadincorrectsize0blobapitestuploadincorrectsizec47250537Tue, 14 Jul 2020 17:19:02 GMT\"0x8D8281A00C3DE5B\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 14 Jul 2020 17:19:02 GMT", + "x-ms-client-request-id" : "039695a3-cdd6-4f4f-bf61-0607b7441c14", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizec47250537?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "44c31a46-1731-4413-a8a8-08a3dee3d7c6" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "77df9095-901e-0010-4502-5a6232000000", + "Date" : "Tue, 14 Jul 2020 17:19:02 GMT", + "x-ms-client-request-id" : "44c31a46-1731-4413-a8a8-08a3dee3d7c6" + }, + "Exception" : null + } ], + "variables" : [ "jtcuploadincorrectsize0blobapitestuploadincorrectsizec47250537", "javablobuploadincorrectsize105800ad666ed1358e41c" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[2].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[2].json new file mode 100644 index 000000000000..5a5e1216e04b --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[2].json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizea0271001d?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "d37e8d0e-2ed0-4aff-817f-5aecbe772444" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D8281A01899BB6", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:03 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "167610af-a01e-0031-6502-5a0f03000000", + "Date" : "Tue, 14 Jul 2020 17:19:03 GMT", + "x-ms-client-request-id" : "d37e8d0e-2ed0-4aff-817f-5aecbe772444" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizea0271001d/javablobuploadincorrectsize1958500e125872c20b445", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "70a6acea-8a74-46ec-a8bf-dd19d4162bbe", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "6RYQPwaVsyQ=", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:03 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 14 Jul 2020 17:19:03 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==", + "ETag" : "0x8D8281A01B9A32A", + "Content-Length" : "0", + "x-ms-request-id" : "d2c931c3-d01e-00f2-7c02-5a8640000000", + "x-ms-client-request-id" : "70a6acea-8a74-46ec-a8bf-dd19d4162bbe" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcuploadincorrectsize&comp=list", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "bdd56435-50ac-4727-9134-747e0bed473e" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "8193fad7-d01e-003e-6d02-5ae2f5000000", + "Body" : "jtcuploadincorrectsizejtcuploadincorrectsize0blobapitestuploadincorrectsizea0271001dTue, 14 Jul 2020 17:19:03 GMT\"0x8D8281A01899BB6\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 14 Jul 2020 17:19:03 GMT", + "x-ms-client-request-id" : "bdd56435-50ac-4727-9134-747e0bed473e", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsizea0271001d?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "cc682a78-2410-4fa2-b4af-8489aeb9b645" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a98ba26c-301e-013b-0902-5a50df000000", + "Date" : "Tue, 14 Jul 2020 17:19:03 GMT", + "x-ms-client-request-id" : "cc682a78-2410-4fa2-b4af-8489aeb9b645" + }, + "Exception" : null + } ], + "variables" : [ "jtcuploadincorrectsize0blobapitestuploadincorrectsizea0271001d", "javablobuploadincorrectsize1958500e125872c20b445" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[3].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[3].json new file mode 100644 index 000000000000..8577b8efce5c --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/BlobAPITestuploadincorrectsize[3].json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize427036766?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "8df45dbd-50b9-4d73-99b5-bd2404f101e5" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D8281A023E3FBF", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:04 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "56b2105f-d01e-00d0-0e02-5ae876000000", + "Date" : "Tue, 14 Jul 2020 17:19:04 GMT", + "x-ms-client-request-id" : "8df45dbd-50b9-4d73-99b5-bd2404f101e5" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize427036766/javablobuploadincorrectsize1366272b06ad9df88a401", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "9f5fdea6-cca6-40d3-b436-202a2cf5b9cc", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "6RYQPwaVsyQ=", + "Last-Modified" : "Tue, 14 Jul 2020 17:19:04 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 14 Jul 2020 17:19:04 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==", + "ETag" : "0x8D8281A0270DF3E", + "Content-Length" : "0", + "x-ms-request-id" : "2f53615d-e01e-003d-0702-5ae1f2000000", + "x-ms-client-request-id" : "9f5fdea6-cca6-40d3-b436-202a2cf5b9cc" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcuploadincorrectsize&comp=list", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "429137e8-db49-453b-afe9-d423893e0e63" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "09b7b005-401e-009a-1102-5ad811000000", + "Body" : "jtcuploadincorrectsizejtcuploadincorrectsize0blobapitestuploadincorrectsize427036766Tue, 14 Jul 2020 17:19:04 GMT\"0x8D8281A023E3FBF\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Tue, 14 Jul 2020 17:19:04 GMT", + "x-ms-client-request-id" : "429137e8-db49-453b-afe9-d423893e0e63", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcuploadincorrectsize0blobapitestuploadincorrectsize427036766?restype=container", + "Headers" : { + "x-ms-version" : "2019-12-12", + "User-Agent" : "azsdk-java-azure-storage-blob/12.8.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "2ddecade-681e-4e3b-8085-81c4f82d0b00" + }, + "Response" : { + "x-ms-version" : "2019-12-12", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "f65a13c8-701e-00bb-4b02-5ab520000000", + "Date" : "Tue, 14 Jul 2020 17:19:04 GMT", + "x-ms-client-request-id" : "2ddecade-681e-4e3b-8085-81c4f82d0b00" + }, + "Exception" : null + } ], + "variables" : [ "jtcuploadincorrectsize0blobapitestuploadincorrectsize427036766", "javablobuploadincorrectsize1366272b06ad9df88a401" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/implementation/UploadUtils.java b/sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/implementation/UploadUtils.java index 6c97ce64d2f0..607d5a0f3223 100644 --- a/sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/implementation/UploadUtils.java +++ b/sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/implementation/UploadUtils.java @@ -47,6 +47,15 @@ public static Mono> uploadFullOrChunked(final Flux d // First buffer is emitted after threshold is breached or there's no more data. // Therefore we can make a decision how to upload data on first element. .switchOnFirst((signal, flux) -> { + // If there is an error before the threshold is reached, propagate the error + if (signal.isOnError()) { + Throwable t = signal.getThrowable(); + if (t != null) { + return Flux.error(t); + } else { + return Flux.error(new IllegalStateException("Source flux failed but cause is unretrievable")); + } + } if (gate.isThresholdBreached()) { // In this case we can pass a flux that can have just one subscriber because // the chunked upload is going to cache the data downstream before sending chunks over the wire.