Skip to content

Instantly share code, notes, and snippets.

@suweya
Last active February 17, 2023 03:39
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save suweya/cc73abedcf8f9378f8a7179178106944 to your computer and use it in GitHub Desktop.
Save suweya/cc73abedcf8f9378f8a7179178106944 to your computer and use it in GitHub Desktop.
OkHttp download file by Okio
import android.os.Environment;
import android.support.annotation.NonNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.Util;
import okio.Buffer;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class FileUtil {
public static Observable<Integer> downloadFileByOkio(@NonNull final String url, @NonNull final File destFile) {
return Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
BufferedSink sink = null;
BufferedSource source = null;
try {
Request request = new Request.Builder().url(url).build();
Response response = HttpClientUtil.getInstance().getOkHttpClient().newCall(request).execute();
ResponseBody body = response.body();
long contentLength = body.contentLength();
source = body.source();
sink = Okio.buffer(Okio.sink(destFile));
Buffer sinkBuffer = sink.buffer();
long totalBytesRead = 0;
int bufferSize = 8 * 1024;
long bytesRead;
while ((bytesRead = source.read(sinkBuffer, bufferSize)) != -1) {
sink.emit();
totalBytesRead += bytesRead;
int progress = (int) ((totalBytesRead * 100) / contentLength);
subscriber.onNext(progress);
}
sink.flush();
} catch (IOException e) {
e.printStackTrace();
subscriber.onError(e);
} finally {
Util.closeQuietly(sink);
Util.closeQuietly(source);
}
subscriber.onCompleted();
}
}).throttleFirst(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public static Observable<Integer> downloadFile(final String url) {
return Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
System.out.println("start download " + Thread.currentThread().getName() + " time " + System.currentTimeMillis());
OkHttpClient client = HttpClientUtil.getInstance().getOkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
inputStream = response.body().byteStream();
outputStream = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "a.txt"));
int totalCount = inputStream.available();
byte[] buffer = new byte[2 * 1024];
int len;
int readLen = 0;
while ((len = inputStream.read(buffer)) != -1 ) {
//System.out.println("download loop " + Thread.currentThread().getName());
outputStream.write(buffer, 0, len);
readLen += len;
subscriber.onNext(readLen);
}
} catch (IOException e) {
e.printStackTrace();
subscriber.onError(e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
subscriber.onCompleted();
}
});
}
}
@saket
Copy link

saket commented Aug 22, 2017

If you forego the progress part, the logic can be compressed to just a couple of lines, that is also easier to read and understand:

Request downloadRequest = new Request.Builder().url(fileUrl).get().build();

Response response = okHttpClient.newCall(downloadRequest).execute();
if (!response.isSuccessful()) {
  throw new IOException("Unexpected code: " + response);
}

File videoFile = ...
try (BufferedSource bufferedSource = response.body().source()) {
  BufferedSink bufferedSink = Okio.buffer(Okio.sink(videoFile));
  bufferedSink.writeAll(bufferedSource);
  bufferedSink.close();
}

@enwokoma
Copy link

@saket. How fast can the download go when using this method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment