Skip to content

Commit e6dfd83

Browse files
committed
issue #336 add the ability to monitor downloads
1 parent ecd5008 commit e6dfd83

File tree

8 files changed

+171
-15
lines changed

8 files changed

+171
-15
lines changed

build/suppressions.xml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<suppressions>
77
<suppress checks="MethodCount" files="Config.java"/>
88
<suppress checks="MethodCount" files="HttpRequest.java"/>
9+
<suppress checks="MethodCount" files="BaseRequest.java"/>
910
<suppress checks="MethodCount" files="JSONArray.java"/>
1011
<suppress checks="MethodCount" files="JSONObject.java"/>
1112
<suppress checks="FileLength" files="JSONObject.java"/>

unirest/src/main/java/kong/unirest/BaseRequest.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ abstract class BaseRequest<R extends HttpRequest> implements HttpRequest<R> {
4545
private Integer socketTimeout;
4646
private Integer connectTimeout;
4747
private Proxy proxy;
48+
private ProgressMonitor downloadMonitor;
4849

4950
BaseRequest(BaseRequest httpRequest) {
5051
this.config = httpRequest.config;
@@ -170,6 +171,12 @@ public R withObjectMapper(ObjectMapper mapper) {
170171
return (R)this;
171172
}
172173

174+
@Override
175+
public R downloadMonitor(ProgressMonitor monitor) {
176+
this.downloadMonitor = monitor;
177+
return (R)this;
178+
}
179+
173180
@Override
174181
public HttpResponse asEmpty() {
175182
return config.getClient().request(this, EmptyResponse::new);
@@ -298,17 +305,17 @@ public void thenConsumeAsync(Consumer<RawResponse> consumer) {
298305

299306
@Override
300307
public HttpResponse<File> asFile(String path) {
301-
return config.getClient().request(this, r -> new FileResponse(r, path));
308+
return config.getClient().request(this, r -> new FileResponse(r, path, downloadMonitor));
302309
}
303310

304311
@Override
305312
public CompletableFuture<HttpResponse<File>> asFileAsync(String path) {
306-
return config.getAsyncClient().request(this, r -> new FileResponse(r, path), new CompletableFuture<>());
313+
return config.getAsyncClient().request(this, r -> new FileResponse(r, path, downloadMonitor), new CompletableFuture<>());
307314
}
308315

309316
@Override
310317
public CompletableFuture<HttpResponse<File>> asFileAsync(String path, Callback<File> callback) {
311-
return config.getAsyncClient().request(this, r -> new FileResponse(r, path), wrap(callback));
318+
return config.getAsyncClient().request(this, r -> new FileResponse(r, path, downloadMonitor), wrap(callback));
312319
}
313320

314321
@Override

unirest/src/main/java/kong/unirest/FileResponse.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,33 @@
2727

2828
import java.io.File;
2929
import java.io.IOException;
30+
import java.io.InputStream;
3031
import java.nio.file.Files;
3132
import java.nio.file.Path;
3233
import java.nio.file.Paths;
3334

3435
public class FileResponse extends BaseResponse<File> {
3536
private File body;
3637

37-
public FileResponse(RawResponse r, String path) {
38+
public FileResponse(RawResponse r, String path, ProgressMonitor downloadMonitor) {
3839
super(r);
3940
try {
4041
Path target = Paths.get(path);
41-
Files.copy(r.getContent(), target);
42+
InputStream content = getContent(r, downloadMonitor, target);
43+
Files.copy(content, target);
4244
body = target.toFile();
4345
} catch (IOException e) {
4446
throw new UnirestException(e);
4547
}
4648
}
4749

50+
private InputStream getContent(RawResponse r, ProgressMonitor downloadMonitor, Path target) {
51+
if(downloadMonitor == null){
52+
return r.getContent();
53+
}
54+
return new MonitoringInputStream(r.getContent(), downloadMonitor, target, r);
55+
}
56+
4857
@Override
4958
public File getBody() {
5059
return body;

unirest/src/main/java/kong/unirest/HttpRequest.java

+7
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ public interface HttpRequest<R extends HttpRequest> {
178178
*/
179179
R proxy(String host, int port);
180180

181+
/**
182+
* sets a download monitor for monitoring the response. this could be used for drawing a progress bar
183+
* @param monitor a ProgressMonitor
184+
* @return
185+
*/
186+
R downloadMonitor(ProgressMonitor monitor);
187+
181188
/**
182189
* Executes the request and returns the response with the body mapped into a String
183190
* @return response
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* The MIT License
3+
*
4+
* Copyright for portions of unirest-java are held by Kong Inc (c) 2013.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining
7+
* a copy of this software and associated documentation files (the
8+
* "Software"), to deal in the Software without restriction, including
9+
* without limitation the rights to use, copy, modify, merge, publish,
10+
* distribute, sublicense, and/or sell copies of the Software, and to
11+
* permit persons to whom the Software is furnished to do so, subject to
12+
* the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be
15+
* included in all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package kong.unirest;
27+
28+
import java.io.IOException;
29+
import java.io.InputStream;
30+
import java.nio.file.Path;
31+
32+
class MonitoringInputStream extends InputStream {
33+
private final InputStream content;
34+
private final ProgressMonitor downloadMonitor;
35+
private long totalSize;
36+
private long byteCount = 0;
37+
private String fileName;
38+
39+
MonitoringInputStream(InputStream content, ProgressMonitor downloadMonitor, Path target, RawResponse contentSize) {
40+
this.content = content;
41+
this.downloadMonitor = downloadMonitor;
42+
this.fileName = target.getFileName().toString();
43+
this.totalSize = getBodySize(contentSize);
44+
}
45+
46+
private Long getBodySize(RawResponse r) {
47+
String header = r.getHeaders().getFirst("Content-Length");
48+
if (header != null && header.length() > 0) {
49+
return Long.valueOf(header);
50+
}
51+
return 0L;
52+
}
53+
54+
@Override
55+
public int read() throws IOException {
56+
return content.read();
57+
}
58+
59+
@Override
60+
public int read(byte[] b) throws IOException {
61+
int read = super.read(b);
62+
monitor(read);
63+
return read;
64+
}
65+
66+
@Override
67+
public int read(byte[] b, int off, int len) throws IOException {
68+
int read = super.read(b, off, len);
69+
monitor(read);
70+
return read;
71+
}
72+
73+
private void monitor(int bytesRead) {
74+
byteCount = byteCount + bytesRead;
75+
downloadMonitor.accept("body", fileName, byteCount, totalSize);
76+
}
77+
78+
@Override
79+
public void close() throws IOException {
80+
content.close();
81+
}
82+
83+
@Override
84+
public long skip(long n) throws IOException {
85+
return content.skip(n);
86+
}
87+
88+
@Override
89+
public int available() throws IOException {
90+
return content.available();
91+
}
92+
93+
@Override
94+
public synchronized void mark(int readlimit) {
95+
content.mark(readlimit);
96+
}
97+
98+
@Override
99+
public boolean markSupported() {
100+
return content.markSupported();
101+
}
102+
103+
@Override
104+
public synchronized void reset() throws IOException {
105+
content.reset();
106+
}
107+
}

unirest/src/test/java/BehaviorTests/DownloadProgressTest.java

+16-7
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,22 @@
3232

3333
import java.io.File;
3434
import java.io.IOException;
35+
import java.util.concurrent.ExecutionException;
3536

3637
import static kong.unirest.TestUtil.rezFile;
38+
import static org.junit.Assert.assertTrue;
3739

3840
public class DownloadProgressTest extends BddTest {
3941
@Rule
4042
public TemporaryFolder disk = new TemporaryFolder();
4143
private File targeFolder;
4244

4345
private TestMonitor monitor;
44-
private File spidey;
4546

4647
@Override
4748
public void setUp() {
4849
super.setUp();
4950
this.monitor = new TestMonitor();
50-
spidey = rezFile("/spidey.jpg");
51-
5251
try {
5352
targeFolder = disk.newFolder("test");
5453
} catch (IOException e) {
@@ -58,11 +57,21 @@ public void setUp() {
5857

5958
@Test
6059
public void canAddUploadProgress() {
61-
Unirest.post(MockServer.BINARYFILE)
62-
//.uploadMonitor(monitor)
63-
.asFile(targeFolder.getPath());
60+
Unirest.get(MockServer.BINARYFILE)
61+
.downloadMonitor(monitor)
62+
.asFile(targeFolder.getPath() + "/spidey.jpg");
63+
64+
monitor.assertSpideyFileDownload("spidey.jpg");
65+
}
66+
67+
@Test
68+
public void canAddUploadProgressAsync() throws Exception {
69+
Unirest.get(MockServer.BINARYFILE)
70+
.downloadMonitor(monitor)
71+
.asFileAsync(targeFolder.getPath() + "/spidey.jpg")
72+
.get();
6473

65-
//assertSpideyFileUpload("spidey.jpg");
74+
monitor.assertSpideyFileDownload("spidey.jpg");
6675
}
6776

6877
}

unirest/src/test/java/BehaviorTests/MockServer.java

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ private static Object file(Request request, Response response) throws Exception
168168
File f = TestUtil.rezFile("/spidey.jpg");
169169
response.raw().setContentType("application/octet-stream");
170170
response.raw().setHeader("Content-Disposition", "attachment;filename=image.jpg");
171+
response.raw().setHeader("Content-Length", String.valueOf(f.length()));
171172
response.status(200);
172173
final ServletOutputStream out = response.raw().getOutputStream();
173174
final FileInputStream in = new FileInputStream(f);

unirest/src/test/java/BehaviorTests/TestMonitor.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,25 @@ public void assertSpideyFileUpload() {
7474

7575
public void assertSpideyFileUpload(String name) {
7676
Stats stat = get(name);
77+
assertEquals("Wrong Expected Length", spidey.length(), stat.total);
7778
assertEquals(12, stat.timesCalled);
78-
assertEquals(asList(4096L, 8192L, 12288L, 16384L, 20480L, 24576L, 28672L,
79-
32768L, 36864L, 40960L, 45056L, 46246L), stat.progress);
80-
assertEquals(spidey.length(), stat.total);
79+
assertEquals(asList(
80+
4096L, 8192L, 12288L, 16384L,
81+
20480L, 24576L, 28672L, 32768L,
82+
36864L, 40960L, 45056L, 46246L),
83+
stat.progress);
84+
}
85+
86+
public void assertSpideyFileDownload(String name) {
87+
Stats stat = get(name);
88+
assertEquals("Wrong Expected Length", spidey.length(), stat.total);
89+
assertEquals(14, stat.timesCalled);
90+
assertEquals(asList(
91+
8192L, 16384L, 24576L, 32768L,
92+
40960L, 49152L, 57344L, 65536L,
93+
73728L, 81920L, 87206L, 92492L,
94+
92491L, 92490L),
95+
stat.progress);
8196
}
8297

8398
static class Stats {

0 commit comments

Comments
 (0)