diff --git a/sdk/storage/azure-storage-blob-cryptography/src/main/java/com/azure/storage/blob/specialized/cryptography/EncryptedBlobAsyncClient.java b/sdk/storage/azure-storage-blob-cryptography/src/main/java/com/azure/storage/blob/specialized/cryptography/EncryptedBlobAsyncClient.java index 0810f6079527..8cb7b625a61d 100644 --- a/sdk/storage/azure-storage-blob-cryptography/src/main/java/com/azure/storage/blob/specialized/cryptography/EncryptedBlobAsyncClient.java +++ b/sdk/storage/azure-storage-blob-cryptography/src/main/java/com/azure/storage/blob/specialized/cryptography/EncryptedBlobAsyncClient.java @@ -34,7 +34,6 @@ import com.azure.storage.blob.options.BlobQueryOptions; import com.azure.storage.blob.options.BlobUploadFromFileOptions; import com.azure.storage.blob.specialized.BlockBlobAsyncClient; -import com.azure.storage.common.Utility; import com.azure.storage.common.implementation.Constants; import com.azure.storage.common.implementation.StorageImplUtils; import com.azure.storage.common.implementation.UploadUtils; @@ -418,9 +417,14 @@ public Mono> uploadWithResponse(BlobParallelUploadOption // Can't use a Collections.emptyMap() because we add metadata for encryption. final Map metadataFinal = options.getMetadata() == null ? new HashMap<>() : options.getMetadata(); - Flux data = options.getDataFlux() == null ? Utility.convertStreamToByteBuffer( - options.getDataStream(), options.getLength(), BLOB_DEFAULT_UPLOAD_BLOCK_SIZE, false) - : options.getDataFlux(); + + final ParallelTransferOptions parallelTransferOptions = + ModelHelper.populateAndApplyDefaults(options.getParallelTransferOptions()); + + Flux data = options.getDataFlux(); + data = UploadUtils.extractByteBuffer(data, options.getOptionalLength(), + parallelTransferOptions.getBlockSizeLong(), options.getDataStream()); + Flux dataFinal = prepareToSendEncryptedRequest(data, metadataFinal); return super.uploadWithResponse(new BlobParallelUploadOptions(dataFinal) .setParallelTransferOptions(options.getParallelTransferOptions()).setHeaders(options.getHeaders()) diff --git a/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncyptedBlockBlobAPITest.groovy b/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncyptedBlockBlobAPITest.groovy index 7175c2dc2b1c..d09b20ac87a8 100644 --- a/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncyptedBlockBlobAPITest.groovy +++ b/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncyptedBlockBlobAPITest.groovy @@ -10,6 +10,7 @@ import com.azure.core.http.HttpResponse import com.azure.core.http.policy.HttpPipelinePolicy import com.azure.core.test.TestMode import com.azure.core.util.BinaryData +import com.azure.core.util.Context import com.azure.core.util.ProgressListener import com.azure.identity.DefaultAzureCredentialBuilder import com.azure.storage.blob.BlobClientBuilder @@ -1919,6 +1920,36 @@ class EncyptedBlockBlobAPITest extends APISpec { 3 * Constants.MB | Constants.MB || 4 // Encryption padding will add an extra block } + def "Encryption upload IS no length"() { + setup: + def randomData = getRandomByteArray(Constants.KB) + def input = new ByteArrayInputStream(randomData) + + when: + ebc.upload(input) + + then: + def stream = new ByteArrayOutputStream() + ebc.downloadStream(stream) + stream.toByteArray() == randomData + } + + def "Encryption upload IS no length with options"() { + setup: + def randomData = getRandomByteArray(Constants.KB) + def payloadAsInputStream = new ByteArrayInputStream(randomData) + def os = new ByteArrayOutputStream() + def blobParallelUploadOptions = new BlobParallelUploadOptions(payloadAsInputStream) + + when: + ebc.uploadWithResponse(blobParallelUploadOptions, null, Context.NONE) + ebc.downloadStream(os) + + then: + notThrown(BlobStorageException) + os.toByteArray() == randomData + } + def getPerCallVersionPolicy() { return new HttpPipelinePolicy() { @Override diff --git a/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLength.json b/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLength.json new file mode 100644 index 000000000000..031f0206b5fb --- /dev/null +++ b/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLength.json @@ -0,0 +1,148 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8?restype=container", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "3f80d3ed-ca4e-4936-bffa-35bcb9990f38" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8DB25B5D8746BFC", + "Last-Modified" : "Thu, 16 Mar 2023 00:31:55 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "ee6775cd-901e-007b-099e-57985e000000", + "Date" : "Thu, 16 Mar 2023 00:31:54 GMT", + "x-ms-client-request-id" : "3f80d3ed-ca4e-4936-bffa-35bcb9990f38" + }, + "Exception" : null + }, { + "Method" : "HEAD", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8/cd65fa1c3cd65fa1cb59398349c4ec107c999408db76", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "d4f0acd6-9989-4182-9ea1-c1be13c35a8b" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "BlobNotFound", + "retry-after" : "0", + "StatusCode" : "404", + "x-ms-request-id" : "ee677a90-901e-007b-799e-57985e000000", + "Date" : "Thu, 16 Mar 2023 00:31:55 GMT", + "x-ms-client-request-id" : "d4f0acd6-9989-4182-9ea1-c1be13c35a8b" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8/cd65fa1c3cd65fa1cb59398349c4ec107c999408db76", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "dd95ec2b-9f5f-43fb-ac07-f06d7e87b407", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "u1ZTN9uHVmM=", + "Last-Modified" : "Thu, 16 Mar 2023 00:31:56 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 16 Mar 2023 00:31:56 GMT", + "Content-MD5" : "9mjzZ51wWP5BcF4+S7Tsmg==", + "ETag" : "0x8DB25B5D95AB583", + "Content-Length" : "0", + "x-ms-request-id" : "fdf9bb00-d01e-006a-169e-5702ea000000", + "x-ms-client-request-id" : "dd95ec2b-9f5f-43fb-ac07-f06d7e87b407" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8/cd65fa1c3cd65fa1cb59398349c4ec107c999408db76", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "7344d37a-de55-4f23-8e49-3466b748388b", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "CD9m/kXuIWY=", + "Last-Modified" : "Thu, 16 Mar 2023 00:31:57 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 16 Mar 2023 00:31:56 GMT", + "Content-MD5" : "PiphWIswaftJOxSvNgkciA==", + "ETag" : "0x8DB25B5D97492C8", + "Content-Length" : "0", + "x-ms-request-id" : "ee677cdb-901e-007b-189e-57985e000000", + "x-ms-client-request-id" : "7344d37a-de55-4f23-8e49-3466b748388b" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8/cd65fa1c3cd65fa1cb59398349c4ec107c999408db76", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "1ec02df6-05c3-4340-8610-cdf313ddda86" + }, + "Response" : { + "x-ms-group" : "$superuser", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 16 Mar 2023 00:31:57 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Thu, 16 Mar 2023 00:31:56 GMT", + "x-ms-resource-type" : "file", + "x-ms-blob-type" : "BlockBlob", + "Content-MD5" : "PiphWIswaftJOxSvNgkciA==", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-meta-encryptiondata" : "{\"EncryptionMode\":\"FullBlob\",\"WrappedContentKey\":{\"KeyId\":\"keyId\",\"EncryptedKey\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\",\"Algorithm\":\"RSA-OAEP-256\"},\"EncryptionAgent\":{\"Protocol\":\"1.0\",\"EncryptionAlgorithm\":\"AES_CBC_256\"},\"ContentEncryptionIV\":\"6NgmBAtUQp5JGUJO1cBFRQ==\",\"KeyWrappingMetadata\":{\"EncryptionLibrary\":\"JavaTrack212.22.0-beta.1\"}}", + "ETag" : "0x8DB25B5D97492C8", + "x-ms-creation-time" : "Thu, 16 Mar 2023 00:31:56 GMT", + "x-ms-permissions" : "rw-r-----", + "Content-Length" : "1040", + "x-ms-request-id" : "fdf9bb9a-d01e-006a-1d9e-5702ea000000", + "Body" : "bxWXBw9reJusCb5tnq9hN4ia/eQdCq077YcvChAGv9rV/3PhjqKiwHvrvt2A2gkiVuZdyyABbOw6EIqaBHE5pDPyrNQ42tU224L+QtoC28XoSkwdlkpt8AzIbBGV5QZIk68xw6mvPoNvkRUh5JRVue55ntYOAvicHJj/7s3IxjkyNtMm3AzxXadTqGexPA8Ho4sEZe98UZnmyhcCZroXeVstKG5o+sFr5n/HEPXJrDwfXVBVwG36K8Kv/qr2gHYuuiIhIdsllMMUkcGrpJGZs7aRR1d8PhYcambd7lOrfVPX8UrSL2eLl9Zrl3Vg16Hv/Jdod48G0VrPXLP6ZiK/E6K230uDEn5iw+uCxaaAhV3sPldJFabhJvuG2uNSWqHD66JIUbMWWjsXbyyBAXikrACAQ9uyua23SEx319FKSqMY78wG1CjxLQhabw537tOIRmxE/lx14s9Ty4Dgt1BaPX5TY40XyEEO2onOkrJ3V+0Y2T19j0A4q7VlAno4Eci2m+D3VUahi9jzOPDQYUw92UEXHzs6VEaxKiV6RBPSPP0TPvvuz36UvmbswDuE8wYizu60/Jz99WQQH+uKDkKPlORsxfCEWGUf2XJt5IeN0WNftHeFMBZr0rJn9+pFoa+a4JuWv3HrUwtY1He4o3ZQdOMe5lvnkNuBqPiE7QTY829BQjyrXa28ErC3jV7doyNQnNIpBf5AeDBPemipO+8t9T5Bjp4HiEhYc6WnCprxDeo7De4aZ/y80GTKhX0bI6pqwbIKzEs3XYzG2bXxDaQiFrV+EPMMxGz1fXGz+IPeuj0hDd4Lxyx2R8ya5gowToFzSYXJ6Shn96aPJjzkev65AKxBZ5MOhE2utkNu2i/IV1vj4vA2hs2PdAA86U39gYqfl+Vb3KAX7fCtSdM5IfA6fddLk7dmiL9EfV2z+6Ma8TBuiQqrs0BnUgzPBnf6NCI8G7y+dpPrMyXrxIIqlva778efiXwmwtyhJtPQJYfjYn0b0PpDHljrFy5121+ChSpPd+Iidol2XbTk3zgbb0r+goC7UDojyrlicEwP+8grr64LUl6tu6kK0s0yTvMEzcgXzkv5YwnjQFdIddJ8xBSV7hj/bjT365h0n4FCwfAnSBODuLwL/qPTyEClWHOIbdPfdYDiKqzxe4S94QdOz3ntwFuygxga2JyS6mppRrHWvu7XWTrqjTvNQx1l2tElI0EuiMe5nGxxYnHhoYg5D+OigHQ39eS60T77Hz0P12aV1hw1vdFO9eAsfXGtwE1zHl8/rNeob4zp8lz9gpiu82BisbmJLKXqv6gMb4VN3toaN3kzDcx2BdKO8CknHIbCiKaFmQW6yRK8O4bYVFYgutRHyr+s4tW0qU65BMIDv6hFk8k=", + "x-ms-owner" : "$superuser", + "x-ms-client-request-id" : "1ec02df6-05c3-4340-8610-cdf313ddda86", + "Content-Type" : "application/octet-stream" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8?restype=container", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "738d8d4f-9a62-495f-999f-454d2b874723" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "ee677e20-901e-007b-469e-57985e000000", + "Date" : "Thu, 16 Mar 2023 00:31:56 GMT", + "x-ms-client-request-id" : "738d8d4f-9a62-495f-999f-454d2b874723" + }, + "Exception" : null + } ], + "variables" : [ "cd65fa1c0cd65fa1cb5993931dfdebdaf26e8401e8a8", "cd65fa1c1cd65fa1cb597644043b974f693ab4290918", "cd65fa1c2cd65fa1cb591337300a2587c69514f01bf4", "cd65fa1c3cd65fa1cb59398349c4ec107c999408db76", "db6cf848-1236-4b4c-b46f-ef3a8c046080" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLengthWithOptions.json b/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLengthWithOptions.json new file mode 100644 index 000000000000..38234b869576 --- /dev/null +++ b/sdk/storage/azure-storage-blob-cryptography/src/test/resources/session-records/EncyptedBlockBlobAPITestEncryptionUploadISNoLengthWithOptions.json @@ -0,0 +1,148 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd?restype=container", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "c40597f0-b74a-47bf-b7ed-d0afd82a2493" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8DB2654E681FA51", + "Last-Modified" : "Thu, 16 Mar 2023 19:30:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "f67f66c9-101e-0065-293d-587486000000", + "Date" : "Thu, 16 Mar 2023 19:30:28 GMT", + "x-ms-client-request-id" : "c40597f0-b74a-47bf-b7ed-d0afd82a2493" + }, + "Exception" : null + }, { + "Method" : "HEAD", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd/6f80bf1236f80bf123f279507006c61fb33f54583b4e", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "2704458e-74bf-48ad-bb34-1893892facb9" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "BlobNotFound", + "retry-after" : "0", + "StatusCode" : "404", + "x-ms-request-id" : "f67f6d08-101e-0065-193d-587486000000", + "Date" : "Thu, 16 Mar 2023 19:30:29 GMT", + "x-ms-client-request-id" : "2704458e-74bf-48ad-bb34-1893892facb9" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd/6f80bf1236f80bf123f279507006c61fb33f54583b4e", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "ad9d4031-bac9-4791-bc59-7afc5cc2ac8f", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "xzRcwpOL2RE=", + "Last-Modified" : "Thu, 16 Mar 2023 19:30:30 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 16 Mar 2023 19:30:30 GMT", + "Content-MD5" : "T8GppmGqbtDSQlv71NX7ig==", + "ETag" : "0x8DB2654E776653E", + "Content-Length" : "0", + "x-ms-request-id" : "ba381b57-c01e-0014-173d-5892ad000000", + "x-ms-client-request-id" : "ad9d4031-bac9-4791-bc59-7afc5cc2ac8f" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd/6f80bf1236f80bf123f279507006c61fb33f54583b4e", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "47b7c329-c09c-4c98-a9a3-90c943d2d41a", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-crc64" : "OO6s3eaxfOc=", + "Last-Modified" : "Thu, 16 Mar 2023 19:30:30 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 16 Mar 2023 19:30:30 GMT", + "Content-MD5" : "9gRaKDypgeZk4Xqd/Fog5w==", + "ETag" : "0x8DB2654E79383FC", + "Content-Length" : "0", + "x-ms-request-id" : "f67f7069-101e-0065-3b3d-587486000000", + "x-ms-client-request-id" : "47b7c329-c09c-4c98-a9a3-90c943d2d41a" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd/6f80bf1236f80bf123f279507006c61fb33f54583b4e", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 azsdk-java-azure-storage-blob-cryptography/12.21.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "7682d301-20cd-4efa-b78f-dce088cfd2a9" + }, + "Response" : { + "x-ms-group" : "$superuser", + "x-ms-lease-status" : "unlocked", + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 16 Mar 2023 19:30:30 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Thu, 16 Mar 2023 19:30:30 GMT", + "x-ms-resource-type" : "file", + "x-ms-blob-type" : "BlockBlob", + "Content-MD5" : "9gRaKDypgeZk4Xqd/Fog5w==", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-meta-encryptiondata" : "{\"EncryptionMode\":\"FullBlob\",\"WrappedContentKey\":{\"KeyId\":\"keyId\",\"EncryptedKey\":\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\",\"Algorithm\":\"RSA-OAEP-256\"},\"EncryptionAgent\":{\"Protocol\":\"1.0\",\"EncryptionAlgorithm\":\"AES_CBC_256\"},\"ContentEncryptionIV\":\"Yf+SKUanYe4Ysp/wVbB79w==\",\"KeyWrappingMetadata\":{\"EncryptionLibrary\":\"JavaTrack212.22.0-beta.1\"}}", + "ETag" : "0x8DB2654E79383FC", + "x-ms-creation-time" : "Thu, 16 Mar 2023 19:30:30 GMT", + "x-ms-permissions" : "rw-r-----", + "Content-Length" : "1040", + "x-ms-request-id" : "ba381c1a-c01e-0014-4c3d-5892ad000000", + "Body" : "tLMoHv9E2J34uICOco8xSwDYTMebFq8Jsyf2IzktCbSrx78Yy/rM2qspIURv8bKQ++wurxO8a/cCKn+L2hvgDJ5Dbtbu6f6BqWo1tViziIM7WhX7x5gnMVFAwq6wDmfrnXjg+28ouYXx0zIA2IrOZu3VG8WZdLfQZSzm+4WcTc8RZEm5hQlkA8l8KNpUMU/eeWklL2pZwMiCgmQNO2wImgZ1D6b/m/t7uMKURkgOR0/xaAKghE8lS26evt47pEJBRPxWRWzceHMyGg46lwi9FqM2tCJc5TON7iT41CNB2EKF7c823UDE6kwcdtzB34v88lzbJf5flAr/eFMCCQPMpVn089RBWEUMZxeQsYaPElxXj+C3XtS6nfi3qZuyZE0J+qjxenbLKg2Lz5QpQjlY6IsX2+IpLMq+tOHGOWJYyKMAkMjBpwoKCX8Me/awVj0U5zpjWiQuXdu0Y2a0aEajBI/wGGBOuXfaOKXzRZOkIvu6yQbOyD0GvzqbYiVdC338+6gNJ1RihMrsh7zJgm8yYc+iqhyfQCiudye3MqV+/M8P0nVhaf0tyvgG1lCMttrC3YPrIZiF7EmAhTA7h0QFff5is5I23YOpojDIaN+90+6wveRZ1vksDoQo/eRPV4HogRICWhQdU51uPBBT24yYZt8pKr2KtBYrY+7qg/l7x2BFFb6xb3/o++kYegCfxWcZ7UexxWZpSvJ81xwEqyY7PDDnIV2Ve0lC4zzVkKO5w+IJen7ROJaEmonYMOV06kl4Aw9YNekRlnVLqnY865VFRdc2+fBVG2r59U0KyLU3+G8Oztfcj0rnE3D/+IsgS3/lLvj7dWuZCpdxBgRC40cHnW6+lUm9wLBO16W7EbI2ZGcDBu0hpPwrYfXOOMPt+C/3m3LdRGU23LTG2/di7aBXNECXz/Q/apDwWmfweMbnENjjaGKiguNqNdXPyYZcJ7oG+h/48wLeiwBQasJkX9ekzrF7regudKK81N9sFvjfGUWyFlfqAqF4RrMZ0jYz8/krrO/CsA2xWJB71X2H7kdzYQuQyaxkttke+8NpYPFrVZQDUfvvjqdba86bw5yy+sWCOxOaS90QKDiKH45Cljlv0RqwSKkz4dAOB+M9diuJgwTN35jfFpUGWpTkr2FmlNpc3Fnp6LIa3RtB1so9gNbvnXyfBl7mluqf6LfbYEg5r6Fnk4cqN00h+cAKY2JwjW2fvS0htSvrP6Q7SuYttGOa/H3Db/4EpZv757NXnGyibtzWsTRwC6hiD8fWy6KVtJ8ixdtUSzo/PhHZvYBwQDJChXDmNdbwUXsDAHG+lmXypGAXBs/cHrmVaY370eNYMA6BH8m3xs677WipsYzqChM9s56no3IfvHHZEKcgGfBN8uE=", + "x-ms-owner" : "$superuser", + "x-ms-client-request-id" : "7682d301-20cd-4efa-b78f-dce088cfd2a9", + "Content-Type" : "application/octet-stream" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/6f80bf1206f80bf123f208889a97e03e62a074d5f8cd?restype=container", + "Headers" : { + "x-ms-version" : "2022-11-02", + "User-Agent" : "azsdk-java-azure-storage-blob/12.22.0-beta.1 (11.0.16.1; Windows 11; 10.0)", + "x-ms-client-request-id" : "3012a4b4-86af-4faa-b6ed-52628c0e9390" + }, + "Response" : { + "x-ms-version" : "2022-11-02", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "f67f7119-101e-0065-5d3d-587486000000", + "Date" : "Thu, 16 Mar 2023 19:30:30 GMT", + "x-ms-client-request-id" : "3012a4b4-86af-4faa-b6ed-52628c0e9390" + }, + "Exception" : null + } ], + "variables" : [ "6f80bf1206f80bf123f208889a97e03e62a074d5f8cd", "6f80bf1216f80bf123f21352585963d51d5374d499f0", "6f80bf1226f80bf123f23170201672a7b0f2647428a1", "6f80bf1236f80bf123f279507006c61fb33f54583b4e", "8961d056-704a-47c3-aa8f-58f6c46a2700" ] +} \ No newline at end of file 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 4c2a7f0afb0f..6e4e2b510043 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 @@ -35,7 +35,6 @@ import com.azure.storage.blob.specialized.BlockBlobClient; import com.azure.storage.blob.specialized.PageBlobAsyncClient; import com.azure.storage.blob.specialized.SpecializedBlobClientBuilder; -import com.azure.storage.common.Utility; import com.azure.storage.common.implementation.BufferStagingArea; import com.azure.storage.common.implementation.Constants; import com.azure.storage.common.implementation.StorageImplUtils; @@ -706,20 +705,8 @@ public Mono> uploadWithResponse(BlobParallelUploadOption headers, metadata, tags, tier, requestConditions, computeMd5, immutabilityPolicy, legalHold); Flux data = options.getDataFlux(); - // no specified length: use azure.core's converter - if (data == null && options.getOptionalLength() == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - parallelTransferOptions.getBlockSizeLong()); - data = FluxUtil.toFluxByteBuffer(options.getDataStream(), chunkSize); - // specified length (legacy requirement): use custom converter. no marking because we buffer anyway. - } else if (data == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - parallelTransferOptions.getBlockSizeLong()); - data = Utility.convertStreamToByteBuffer( - options.getDataStream(), options.getOptionalLength(), chunkSize, false); - } + data = UploadUtils.extractByteBuffer(data, options.getOptionalLength(), + parallelTransferOptions.getBlockSizeLong(), options.getDataStream()); return UploadUtils.uploadFullOrChunked(data, ModelHelper.wrapBlobOptions(parallelTransferOptions), uploadInChunksFunction, uploadFullBlobFunction); 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 4e9881a0a6ee..389854023c6e 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 @@ -5,12 +5,15 @@ import com.azure.core.http.rest.Response; import com.azure.core.util.CoreUtils; +import com.azure.core.util.FluxUtil; import com.azure.core.util.logging.ClientLogger; import com.azure.storage.common.ParallelTransferOptions; +import com.azure.storage.common.Utility; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; @@ -191,4 +194,29 @@ public byte[] getMd5() { return CoreUtils.clone(md5); } } + + /** + * Extracts the byte buffer for upload operations. + * + * @param data the {@link Flux} of {@link ByteBuffer}, if specified. + * @param optionalLength length of data. + * @param blockSize the block size (chunk size) to transfer at a time. + * @param dataStream the {@link InputStream}, if specified. + * @return the updated {@link Flux} of {@link ByteBuffer}. + */ + public static Flux extractByteBuffer(Flux data, Long optionalLength, Long blockSize, + InputStream dataStream) { + // no specified length: use azure.core's converter + if (data == null && optionalLength == null) { + // We can only buffer up to max int due to restrictions in ByteBuffer. + int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, blockSize); + data = FluxUtil.toFluxByteBuffer(dataStream, chunkSize); + // specified length (legacy requirement): use custom converter. no marking because we buffer anyway. + } else if (data == null) { + // We can only buffer up to max int due to restrictions in ByteBuffer. + int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, blockSize); + data = Utility.convertStreamToByteBuffer(dataStream, optionalLength, chunkSize, false); + } + return data; + } } diff --git a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/DataLakeFileAsyncClient.java b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/DataLakeFileAsyncClient.java index 72281da82783..cb6d5aa92c3c 100644 --- a/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/DataLakeFileAsyncClient.java +++ b/sdk/storage/azure-storage-file-datalake/src/main/java/com/azure/storage/file/datalake/DataLakeFileAsyncClient.java @@ -612,20 +612,8 @@ public Mono> uploadWithResponse(FileParallelUploadOptions opt // if BinaryData is present, convert it to Flux Byte Buffer Flux data = binaryData != null ? binaryData.toFluxByteBuffer() : options.getDataFlux(); - // no specified length: use azure.core's converter - if (data == null && options.getOptionalLength() == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - validatedParallelTransferOptions.getBlockSizeLong()); - data = FluxUtil.toFluxByteBuffer(options.getDataStream(), chunkSize); - // specified length (legacy requirement): use custom converter. no marking because we buffer anyway. - } else if (data == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - validatedParallelTransferOptions.getBlockSizeLong()); - data = Utility.convertStreamToByteBuffer( - options.getDataStream(), options.getOptionalLength(), chunkSize, false); - } + data = UploadUtils.extractByteBuffer(data, options.getOptionalLength(), + validatedParallelTransferOptions.getBlockSizeLong(), options.getDataStream()); return createWithResponse(options.getPermissions(), options.getUmask(), options.getHeaders(), options.getMetadata(), validatedRequestConditions) diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java index 7e49bf47d57b..594c94dd2fbd 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java @@ -2060,20 +2060,8 @@ Mono> uploadWithResponse(ShareFileUploadOptions op }; Flux data = options.getDataFlux(); - // no specified length: use azure.core's converter - if (data == null && options.getLength() == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - validatedParallelTransferOptions.getBlockSizeLong()); - data = FluxUtil.toFluxByteBuffer(options.getDataStream(), chunkSize); - // specified length (legacy requirement): use custom converter. no marking because we buffer anyway. - } else if (data == null) { - // We can only buffer up to max int due to restrictions in ByteBuffer. - int chunkSize = (int) Math.min(Constants.MAX_INPUT_STREAM_CONVERTER_BUFFER_LENGTH, - validatedParallelTransferOptions.getBlockSizeLong()); - data = Utility.convertStreamToByteBuffer( - options.getDataStream(), options.getLength(), chunkSize, false); - } + data = UploadUtils.extractByteBuffer(data, options.getLength(), + validatedParallelTransferOptions.getBlockSizeLong(), options.getDataStream()); return UploadUtils.uploadFullOrChunked(data, validatedParallelTransferOptions, uploadInChunks, uploadFull); } catch (RuntimeException ex) {