diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 6ce9ca8c6e2a..8e1b10a0efd5 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1429,6 +1429,30 @@ public static Builder newBuilder() { */ Blob create(BlobInfo blobInfo, byte[] content, BlobTargetOption... options); + /** + * Creates a new blob with the sub array of the given byte array. Direct upload is used to upload + * {@code content}. For large content, {@link #writer} is recommended as it uses resumable upload. + * MD5 and CRC32C hashes of {@code content} are computed and used for validating transferred data. + * Accepts a userProject {@link BlobGetOption} option, which defines the project id to assign + * operational costs. + * + *
Example of creating a blob from a byte array. + * + *
{@code
+ * String bucketName = "my_unique_bucket";
+ * String blobName = "my_blob_name";
+ * BlobId blobId = BlobId.of(bucketName, blobName);
+ * BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("text/plain").build();
+ * Blob blob = storage.create(blobInfo, "Hello, World!".getBytes(UTF_8), 7, 5);
+ * }
+ *
+ * @return a [@code Blob} with complete information
+ * @throws StorageException upon failure
+ * @see Hashes and ETags
+ */
+ Blob create(
+ BlobInfo blobInfo, byte[] content, int offset, int length, BlobTargetOption... options);
+
/**
* Creates a new blob. Direct upload is used to upload {@code content}. For large content, {@link
* #writer} is recommended as it uses resumable upload. By default any md5 and crc32c values in
diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
index ec9fdffbca5e..ac4da4c32eea 100644
--- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
+++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
@@ -149,6 +149,22 @@ public Blob create(BlobInfo blobInfo, byte[] content, BlobTargetOption... option
return internalCreate(updatedInfo, content, options);
}
+ @Override
+ public Blob create(
+ BlobInfo blobInfo, byte[] content, int offset, int length, BlobTargetOption... options) {
+ content = firstNonNull(content, EMPTY_BYTE_ARRAY);
+ byte[] subContent = Arrays.copyOfRange(content, offset, offset + length);
+ BlobInfo updatedInfo =
+ blobInfo
+ .toBuilder()
+ .setMd5(BaseEncoding.base64().encode(Hashing.md5().hashBytes(subContent).asBytes()))
+ .setCrc32c(
+ BaseEncoding.base64()
+ .encode(Ints.toByteArray(Hashing.crc32c().hashBytes(subContent).asInt())))
+ .build();
+ return internalCreate(updatedInfo, subContent, options);
+ }
+
@Override
@Deprecated
public Blob create(BlobInfo blobInfo, InputStream content, BlobWriteOption... options) {
diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java
index 393c7ff3bfcf..ef1fb677edcd 100644
--- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java
+++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java
@@ -97,8 +97,11 @@ public class StorageImplTest {
private static final String BLOB_NAME2 = "n2";
private static final String BLOB_NAME3 = "n3";
private static final byte[] BLOB_CONTENT = {0xD, 0xE, 0xA, 0xD};
+ private static final byte[] BLOB_SUB_CONTENT = {0xE, 0xA};
private static final String CONTENT_MD5 = "O1R4G1HJSDUISJjoIYmVhQ==";
private static final String CONTENT_CRC32C = "9N3EPQ==";
+ private static final String SUB_CONTENT_MD5 = "5e7c7CdasUiOn3BO560jPg==";
+ private static final String SUB_CONTENT_CRC32C = "bljNYA==";
private static final int DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024;
private static final String BASE64_KEY = "JVzfVl8NLD9FjedFuStegjRfES5ll5zc59CIXw572OA=";
private static final Key KEY =
@@ -445,6 +448,34 @@ public void testCreateBlob() throws IOException {
assertEquals(-1, byteStream.read(streamBytes));
}
+ @Test
+ public void testCreateBlobWithSubArrayFromByteArray() throws IOException {
+ Capture