1818import org .apache .commons .httpclient .HttpStatus ;
1919import org .apache .commons .httpclient .methods .GetMethod ;
2020
21- import java .io .BufferedInputStream ;
21+ import okio .Throttler ;
22+ import okio .Source ;
23+ import okio .BufferedSink ;
24+ import okio .Okio ;
25+
2226import java .io .File ;
23- import java .io .FileOutputStream ;
2427import java .io .IOException ;
2528import java .util .Date ;
2629import java .util .HashSet ;
@@ -44,6 +47,7 @@ public class DownloadFileRemoteOperation extends RemoteOperation {
4447 private long modificationTimestamp = 0 ;
4548 private String eTag = "" ;
4649 private GetMethod getMethod ;
50+ private final Throttler throttler = new Throttler ();
4751
4852 private String remotePath ;
4953 private String temporalFolderPath ;
@@ -57,8 +61,16 @@ public DownloadFileRemoteOperation(String remotePath, String temporalFolderPath)
5761 this .temporalFolderPath = temporalFolderPath ;
5862 }
5963
60- @ Override
61- protected RemoteOperationResult run (OwnCloudClient client ) {
64+ /**
65+ * @param limit Maximum download speed in bytes per second.
66+ * Disabled by default (limit 0).
67+ */
68+ public void setBandwidthLimit (long limit ) {
69+ throttler .bytesPerSecond (limit );
70+ }
71+
72+ @ Override
73+ protected RemoteOperationResult run (OwnCloudClient client ) {
6274 RemoteOperationResult result ;
6375
6476 /// download will be performed to a temporal file, then moved to the final location
@@ -88,7 +100,11 @@ private int downloadFile(OwnCloudClient client, File targetFile) throws IOExcept
88100 getMethod = new GetMethod (client .getFilesDavUri (remotePath ));
89101 Iterator <OnDatatransferProgressListener > it ;
90102
91- FileOutputStream fos = null ;
103+ // TODO If the upload and download limits should be global then the same throttler can be used for
104+ // all instances of this and the upload class.
105+ Source bufferSource = null ;
106+ Source throttledBufferSource = null ;
107+ BufferedSink bufferSink = null ;
92108 try {
93109 status = client .executeMethod (getMethod );
94110 if (isSuccess (status )) {
@@ -98,25 +114,26 @@ private int downloadFile(OwnCloudClient client, File targetFile) throws IOExcept
98114 Log_OC .e (TAG , "Error creating file " + targetFile .getAbsolutePath (), ex );
99115 throw new CreateLocalFileException (targetFile .getPath (), ex );
100116 }
101- BufferedInputStream bis = new BufferedInputStream (getMethod .getResponseBodyAsStream ());
102- fos = new FileOutputStream (targetFile );
117+ bufferSource = Okio .source (getMethod .getResponseBodyAsStream ());
118+ throttledBufferSource = throttler .source (bufferSource );
119+ bufferSink = Okio .buffer (Okio .sink (targetFile ));
120+
103121 long transferred = 0 ;
104122
105123 Header contentLength = getMethod .getResponseHeader ("Content-Length" );
106124 long totalToTransfer = (contentLength != null &&
107- contentLength .getValue ().length () > 0 ) ?
108- Long .parseLong (contentLength .getValue ()) : 0 ;
125+ contentLength .getValue ().length () > 0 ) ?
126+ Long .parseLong (contentLength .getValue ()) : 0 ;
109127
110- byte [] bytes = new byte [ 4096 ] ;
111- int readResult ;
112- while (( readResult = bis . read ( bytes )) != - 1 ) {
128+ long readResult ;
129+ while (( readResult = throttledBufferSource . read ( bufferSink . getBuffer (), 4096 )) != - 1 ) {
130+ bufferSink . emitCompleteSegments ();
113131 synchronized (mCancellationRequested ) {
114132 if (mCancellationRequested .get ()) {
115133 getMethod .abort ();
116134 throw new OperationCancelledException ();
117135 }
118136 }
119- fos .write (bytes , 0 , readResult );
120137 transferred += readResult ;
121138 synchronized (mDataTransferListeners ) {
122139 it = mDataTransferListeners .iterator ();
@@ -126,6 +143,7 @@ private int downloadFile(OwnCloudClient client, File targetFile) throws IOExcept
126143 }
127144 }
128145 }
146+ bufferSink .flush ();
129147 // Check if the file is completed
130148 // if transfer-encoding: chunked we cannot check if the file is complete
131149 Header transferEncodingHeader = getMethod .getResponseHeader ("Transfer-Encoding" );
@@ -163,7 +181,11 @@ private int downloadFile(OwnCloudClient client, File targetFile) throws IOExcept
163181 }
164182
165183 } finally {
166- if (fos != null ) fos .close ();
184+ // TODO Any of these need try statements? Which of these are even necessary? (Been a while since I last dealt with buffers)
185+ if (bufferSource != null ) bufferSource .close ();
186+ if (throttledBufferSource != null ) throttledBufferSource .close ();
187+ if (bufferSink != null ) bufferSink .close ();
188+
167189 if (!savedFile && targetFile .exists ()) {
168190 targetFile .delete ();
169191 }
0 commit comments