diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java index 3d7febfd556b..4d9214ef5929 100644 --- a/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java +++ b/gcloud-java-storage/src/main/java/com/google/gcloud/spi/DefaultStorageRpc.java @@ -461,12 +461,20 @@ public Tuple read(StorageObject from, Map options, lo public void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, int length, boolean last) { try { + if (length == 0 && !last) { + return; + } GenericUrl url = new GenericUrl(uploadId); HttpRequest httpRequest = storage.getRequestFactory().buildPutRequest(url, new ByteArrayContent(null, toWrite, toWriteOffset, length)); long limit = destOffset + length; StringBuilder range = new StringBuilder("bytes "); - range.append(destOffset).append('-').append(limit - 1).append('/'); + if (length == 0) { + range.append('*'); + } else { + range.append(destOffset).append('-').append(limit - 1); + } + range.append('/'); if (last) { range.append(limit); } else { diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java index 38521ae5e137..a411cdd60bfb 100644 --- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java +++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/it/ITStorageTest.java @@ -823,6 +823,29 @@ public void testReadAndWriteChannels() throws IOException { assertTrue(storage.delete(BUCKET, blobName)); } + @Test + public void testReadAndWriteChannelsWithDifferentFileSize() throws IOException { + String blobNamePrefix = "test-read-and-write-channels-blob-"; + int[] blobSizes = {0, 700, 1024 * 256, 2 * 1024 * 1024, 4 * 1024 * 1024, 4 * 1024 * 1024 + 1}; + Random rnd = new Random(); + for (int blobSize : blobSizes) { + String blobName = blobNamePrefix + blobSize; + BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build(); + byte[] bytes = new byte[blobSize]; + rnd.nextBytes(bytes); + try (WriteChannel writer = storage.writer(blob)) { + writer.write(ByteBuffer.wrap(BLOB_BYTE_CONTENT)); + } + ByteBuffer readBytes; + try (ReadChannel reader = storage.reader(blob.blobId())) { + readBytes = ByteBuffer.allocate(BLOB_BYTE_CONTENT.length); + reader.read(readBytes); + } + assertArrayEquals(BLOB_BYTE_CONTENT, readBytes.array()); + assertTrue(storage.delete(BUCKET, blobName)); + } + } + @Test public void testReadAndWriteCaptureChannels() throws IOException { String blobName = "test-read-and-write-capture-channels-blob";