Skip to content

Commit dce2d11

Browse files
committed
fix: Correctly calculate Content-Length when reading from a stream
1 parent 7af7b98 commit dce2d11

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

src/intTest/java/com/box/sdk/BoxFileIT.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,27 @@ public void getRepresentationContentSucceeds() throws InterruptedException {
146146
}
147147
}
148148

149+
@Test
150+
public void getRepresentationContentWithExtractedTextSucceeds() throws InterruptedException {
151+
BoxAPIConnection api = jwtApiForServiceAccount();
152+
String fileName = "text.pdf";
153+
BoxFile file = null;
154+
try {
155+
file = uploadSampleFileToUniqueFolder(api, fileName);
156+
final String fileId = file.getID();
157+
String representationHint = "[extracted_text]";
158+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
159+
Retry.retry(() -> {
160+
new BoxFile(api, fileId).getRepresentationContent(representationHint, outputStream);
161+
byte[] downloadedRepresentationContent = outputStream.toByteArray();
162+
String text = new String(downloadedRepresentationContent, StandardCharsets.UTF_8);
163+
assertTrue(text.contains("Lorem ipsum"));
164+
}, 5, 100);
165+
} finally {
166+
deleteFile(file);
167+
}
168+
}
169+
149170
@Test
150171
public void uploadFileStreamSucceeds() {
151172
BoxAPIConnection api = jwtApiForServiceAccount();
@@ -156,7 +177,7 @@ public void uploadFileStreamSucceeds() {
156177

157178
BoxFile uploadedFile = null;
158179
try {
159-
InputStream uploadStream = new ByteArrayInputStream(fileContent);
180+
InputStream uploadStream = new ByteArrayInputStream(fileContent);
160181
BoxFile.Info uploadedFileInfo = folder.uploadFile(uploadStream, BoxFileIT.generateString());
161182
uploadedFile = uploadedFileInfo.getResource();
162183

@@ -552,11 +573,11 @@ public void canPaginateOverListOfVersions() {
552573

553574
byte[] fileBytes = "Version 2".getBytes(StandardCharsets.UTF_8);
554575
uploadedFile.uploadNewVersion(
555-
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));
576+
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));
556577

557578
fileBytes = "Version 3".getBytes(StandardCharsets.UTF_8);
558579
uploadedFile.uploadNewVersion(
559-
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));
580+
new ByteArrayInputStream(fileBytes), null, fileBytes.length, mock(ProgressListener.class));
560581

561582
Collection<BoxFileVersion> versionsPart1 = uploadedFile.getVersionsRange(0, 1);
562583
assertThat(versionsPart1.size(), is(1));

src/main/java/com/box/sdk/BinaryBodyUtils.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
final class BinaryBodyUtils {
1111
private static final int BUFFER_SIZE = 8192;
12+
private static final String X_ORIGINAL_CONTENT_LENGTH = "X-Original-Content-Length";
1213

1314
private BinaryBodyUtils() {
1415
// utility class has no public constructor
@@ -73,12 +74,36 @@ static void writeStreamWithContentLength(BoxAPIResponse response, OutputStream o
7374
} else {
7475
input = response.getBody();
7576
}
76-
writeStreamTo(input, output, response.getContentLength());
77+
writeStreamTo(input, output, getContentLengthFromAPIResponse(response));
7778
} finally {
7879
response.close();
7980
}
8081
}
8182

83+
/**
84+
* Get the content length from the API response.
85+
* In some cases, the Content-Length is not provided in the response headers.
86+
* This could happen when getting the content representation for a compressed data.
87+
* In that case the API will switch to chunk mode and provide the length in the "X-Original-Content-Length" header.
88+
*
89+
* @param response API response.
90+
* @return Content length.
91+
*/
92+
private static long getContentLengthFromAPIResponse(BoxAPIResponse response) {
93+
long length = response.getContentLength();
94+
try {
95+
if (length == -1 && response.getHeaders().containsKey(X_ORIGINAL_CONTENT_LENGTH)) {
96+
length = Integer.parseInt(response.getHeaders().get(X_ORIGINAL_CONTENT_LENGTH).get(0));
97+
}
98+
} catch (NumberFormatException e) {
99+
throw new RuntimeException(
100+
"Invalid content length: " + response.getHeaders().get("X-Original-Content-Length"
101+
).get(0));
102+
}
103+
104+
return length;
105+
}
106+
82107
/**
83108
* Writes content of input stream to provided output.
84109
*
@@ -127,7 +152,7 @@ static void writeStreamTo(InputStream input, OutputStream output, long expectedL
127152
}
128153
if (totalBytesRead != expectedLength) {
129154
throw new IOException("Stream ended prematurely. Expected " + expectedLength
130-
+ " bytes, but read " + totalBytesRead + " bytes.");
155+
+ " bytes, but read " + totalBytesRead + " bytes.");
131156
}
132157
} catch (IOException e) {
133158
throw new RuntimeException("Error during streaming: " + e.getMessage(), e);
11.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)