Tracking Progress of Multipart File Upload Using Okhttp

Tracking progress of multipart file upload using OKHTTP

You have to create a custom RequestBody and override writeTo method, and there you have to send your files down the sink in segments. It is very important that you flush the sink after each segment, otherwise your progress bar will fill up quickly without the file being actually sent over the network, because the contents will stay in the sink (which acts like a buffer).

public class CountingFileRequestBody extends RequestBody {

private static final int SEGMENT_SIZE = 2048; // okio.Segment.SIZE

private final File file;
private final ProgressListener listener;
private final String contentType;

public CountingFileRequestBody(File file, String contentType, ProgressListener listener) {
this.file = file;
this.contentType = contentType;
this.listener = listener;
}

@Override
public long contentLength() {
return file.length();
}

@Override
public MediaType contentType() {
return MediaType.parse(contentType);
}

@Override
public void writeTo(BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file);
long total = 0;
long read;

while ((read = source.read(sink.buffer(), SEGMENT_SIZE)) != -1) {
total += read;
sink.flush();
this.listener.transferred(total);

}
} finally {
Util.closeQuietly(source);
}
}

public interface ProgressListener {
void transferred(long num);
}

}

You can find a complete implementation that supports displaying progress in an AdapterView and also cancelling uploads at my gist: https://gist.github.com/eduardb/dd2dc530afd37108e1ac

OKHTTP 3 Tracking Multipart upload progress

You can decorate your OkHttp request body to count the number of bytes written when writing it; in order to accomplish this task, wrap your MultiPart RequestBody in this RequestBody with an instance of Listener and Voila!

public class ProgressRequestBody extends RequestBody {

protected RequestBody mDelegate;
protected Listener mListener;
protected CountingSink mCountingSink;

public ProgressRequestBody(RequestBody delegate, Listener listener) {
mDelegate = delegate;
mListener = listener;
}

@Override
public MediaType contentType() {
return mDelegate.contentType();
}

@Override
public long contentLength() {
try {
return mDelegate.contentLength();
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}

@Override
public void writeTo(BufferedSink sink) throws IOException {
mCountingSink = new CountingSink(sink);
BufferedSink bufferedSink = Okio.buffer(mCountingSink);
mDelegate.writeTo(bufferedSink);
bufferedSink.flush();
}

protected final class CountingSink extends ForwardingSink {
private long bytesWritten = 0;
public CountingSink(Sink delegate) {
super(delegate);
}
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
bytesWritten += byteCount;
mListener.onProgress((int) (100F * bytesWritten / contentLength()));
}
}

public interface Listener {
void onProgress(int progress);
}
}

Check this link for more.

Uploading a large file in multipart using OkHttp

From the OkHttp Recipes page, this code uploads an image to Imgur:

private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();

Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

System.out.println(response.body().string());
}

You'll need to adapt this to S3, but the classes you need should be the same.

okhttp multipart image upload with file name

Get OkHttp 2.1, and use MultipartBuilder.addFormDataPart() which takes the filename as a parameter.



Related Topics



Leave a reply



Submit