Skip to content

Commit 474dfae

Browse files
feat: Add shouldReturnRawInputStream option to Get requests (#872)
* feat: Add shouldReturnRawInputStream option to Get requests * lint, clarify documentation
1 parent ee7c236 commit 474dfae

File tree

5 files changed

+89
-3
lines changed

5 files changed

+89
-3
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ private Storage.BlobSourceOption toSourceOptions(BlobInfo blobInfo) {
117117
return Storage.BlobSourceOption.decryptionKey((String) getValue());
118118
case USER_PROJECT:
119119
return Storage.BlobSourceOption.userProject((String) getValue());
120+
case RETURN_RAW_INPUT_STREAM:
121+
return Storage.BlobSourceOption.shouldReturnRawInputStream((boolean) getValue());
120122
default:
121123
throw new AssertionError("Unexpected enum value");
122124
}
@@ -136,6 +138,8 @@ private Storage.BlobGetOption toGetOption(BlobInfo blobInfo) {
136138
return Storage.BlobGetOption.userProject((String) getValue());
137139
case CUSTOMER_SUPPLIED_KEY:
138140
return Storage.BlobGetOption.decryptionKey((String) getValue());
141+
case RETURN_RAW_INPUT_STREAM:
142+
return Storage.BlobGetOption.shouldReturnRawInputStream((boolean) getValue());
139143
default:
140144
throw new AssertionError("Unexpected enum value");
141145
}
@@ -200,6 +204,16 @@ public static BlobSourceOption userProject(String userProject) {
200204
return new BlobSourceOption(StorageRpc.Option.USER_PROJECT, userProject);
201205
}
202206

207+
/**
208+
* Returns an option for whether the request should return the raw input stream, instead of
209+
* automatically decompressing the content. By default, this is false for Blob.downloadTo(), but
210+
* true for ReadChannel.read().
211+
*/
212+
public static BlobSourceOption shouldReturnRawInputStream(boolean shouldReturnRawInputStream) {
213+
return new BlobSourceOption(
214+
StorageRpc.Option.RETURN_RAW_INPUT_STREAM, shouldReturnRawInputStream);
215+
}
216+
203217
static Storage.BlobSourceOption[] toSourceOptions(
204218
BlobInfo blobInfo, BlobSourceOption... options) {
205219
Storage.BlobSourceOption[] convertedOptions = new Storage.BlobSourceOption[options.length];

google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,16 @@ public static BlobSourceOption decryptionKey(String key) {
847847
public static BlobSourceOption userProject(String userProject) {
848848
return new BlobSourceOption(StorageRpc.Option.USER_PROJECT, userProject);
849849
}
850+
851+
/**
852+
* Returns an option for whether the request should return the raw input stream, instead of
853+
* automatically decompressing the content. By default, this is false for Blob.downloadTo(), but
854+
* true for ReadChannel.read().
855+
*/
856+
public static BlobSourceOption shouldReturnRawInputStream(boolean shouldReturnRawInputStream) {
857+
return new BlobSourceOption(
858+
StorageRpc.Option.RETURN_RAW_INPUT_STREAM, shouldReturnRawInputStream);
859+
}
850860
}
851861

852862
/** Class for specifying blob get options. */
@@ -862,6 +872,10 @@ private BlobGetOption(StorageRpc.Option rpcOption, String value) {
862872
super(rpcOption, value);
863873
}
864874

875+
private BlobGetOption(StorageRpc.Option rpcOption, boolean value) {
876+
super(rpcOption, value);
877+
}
878+
865879
/**
866880
* Returns an option for blob's data generation match. If this option is used the request will
867881
* fail if blob's generation does not match. The generation value to compare with the actual
@@ -953,6 +967,16 @@ public static BlobGetOption decryptionKey(Key key) {
953967
public static BlobGetOption decryptionKey(String key) {
954968
return new BlobGetOption(StorageRpc.Option.CUSTOMER_SUPPLIED_KEY, key);
955969
}
970+
971+
/**
972+
* Returns an option for whether the request should return the raw input stream, instead of
973+
* automatically decompressing the content. By default, this is false for Blob.downloadTo(), but
974+
* true for ReadChannel.read().
975+
*/
976+
public static BlobGetOption shouldReturnRawInputStream(boolean shouldReturnRawInputStream) {
977+
return new BlobGetOption(
978+
StorageRpc.Option.RETURN_RAW_INPUT_STREAM, shouldReturnRawInputStream);
979+
}
956980
}
957981

958982
/** Class for specifying bucket list options. */

google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,6 @@ private Get createReadRequest(StorageObject from, Map<Option, ?> options) throws
681681
.setIfGenerationNotMatch(Option.IF_GENERATION_NOT_MATCH.getLong(options))
682682
.setUserProject(Option.USER_PROJECT.getString(options));
683683
setEncryptionHeaders(req.getRequestHeaders(), ENCRYPTION_KEY_PREFIX, options);
684-
req.setReturnRawInputStream(true);
685684
return req;
686685
}
687686

@@ -692,9 +691,15 @@ public long read(
692691
Scope scope = tracer.withSpan(span);
693692
try {
694693
Get req = createReadRequest(from, options);
694+
Boolean shouldReturnRawInputStream = Option.RETURN_RAW_INPUT_STREAM.getBoolean(options);
695+
if (shouldReturnRawInputStream != null) {
696+
req.setReturnRawInputStream(shouldReturnRawInputStream);
697+
} else {
698+
req.setReturnRawInputStream(false);
699+
}
695700
req.getMediaHttpDownloader().setBytesDownloaded(position);
696701
req.getMediaHttpDownloader().setDirectDownloadEnabled(true);
697-
req.executeMediaAndDownloadTo(outputStream);
702+
req.executeMedia().download(outputStream);
698703
return req.getMediaHttpDownloader().getNumBytesDownloaded();
699704
} catch (IOException ex) {
700705
span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage()));
@@ -717,6 +722,12 @@ public Tuple<String, byte[]> read(
717722
try {
718723
checkArgument(position >= 0, "Position should be non-negative, is " + position);
719724
Get req = createReadRequest(from, options);
725+
Boolean shouldReturnRawInputStream = Option.RETURN_RAW_INPUT_STREAM.getBoolean(options);
726+
if (shouldReturnRawInputStream != null) {
727+
req.setReturnRawInputStream(shouldReturnRawInputStream);
728+
} else {
729+
req.setReturnRawInputStream(true);
730+
}
720731
StringBuilder range = new StringBuilder();
721732
range.append("bytes=").append(position).append("-").append(position + bytes - 1);
722733
HttpHeaders requestHeaders = req.getRequestHeaders();

google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ enum Option {
6868
SERVICE_ACCOUNT_EMAIL("serviceAccount"),
6969
SHOW_DELETED_KEYS("showDeletedKeys"),
7070
REQUESTED_POLICY_VERSION("optionsRequestedPolicyVersion"),
71-
DETECT_CONTENT_TYPE("detectContentType");
71+
DETECT_CONTENT_TYPE("detectContentType"),
72+
RETURN_RAW_INPUT_STREAM("returnRawInputStream");
7273

7374
private final String value;
7475

google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
import java.io.ByteArrayOutputStream;
105105
import java.io.File;
106106
import java.io.FileInputStream;
107+
import java.io.FileOutputStream;
107108
import java.io.IOException;
108109
import java.io.InputStream;
109110
import java.net.URL;
@@ -127,6 +128,7 @@
127128
import java.util.logging.Level;
128129
import java.util.logging.Logger;
129130
import java.util.zip.GZIPInputStream;
131+
import java.util.zip.GZIPOutputStream;
130132
import javax.crypto.spec.SecretKeySpec;
131133
import org.apache.http.client.HttpClient;
132134
import org.apache.http.client.methods.HttpPost;
@@ -802,6 +804,40 @@ public void testGetBlobFailNonExistingGeneration() {
802804
}
803805
}
804806

807+
@Test
808+
public void testGetBlobRawInput() throws IOException {
809+
Path file = File.createTempFile("temp", ".txt").toPath();
810+
Files.write(file, "hello world".getBytes());
811+
812+
File gzippedFile = File.createTempFile("temp", ".gz");
813+
814+
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream(gzippedFile));
815+
Files.copy(file, gzipOutputStream);
816+
gzipOutputStream.close();
817+
818+
String blobName = "zipped_blob";
819+
BlobId blobId = BlobId.of(BUCKET, blobName);
820+
BlobInfo blobInfo =
821+
BlobInfo.newBuilder(blobId).setContentEncoding("gzip").setContentType("text/plain").build();
822+
823+
storage.createFrom(blobInfo, gzippedFile.toPath());
824+
825+
Path rawInputGzippedFile = File.createTempFile("rawinputgzippedfile", ".txt").toPath();
826+
Blob blob = storage.get(blobId);
827+
828+
blob.downloadTo(rawInputGzippedFile, Blob.BlobSourceOption.shouldReturnRawInputStream(true));
829+
830+
assertArrayEquals(
831+
Files.readAllBytes(gzippedFile.toPath()), Files.readAllBytes(rawInputGzippedFile));
832+
833+
Path unzippedFile = File.createTempFile("unzippedfile", ".txt").toPath();
834+
storage
835+
.get(blobId)
836+
.downloadTo(unzippedFile, Blob.BlobSourceOption.shouldReturnRawInputStream(false));
837+
838+
assertArrayEquals("hello world".getBytes(), Files.readAllBytes(unzippedFile));
839+
}
840+
805841
@Test(timeout = 5000)
806842
public void testListBlobsSelectedFields() throws InterruptedException {
807843
String[] blobNames = {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy