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
What Happens to Older Clients When You Migrate an App Server from Gcm to Fcm
How to Scroll Recyclerview Programmatically
How to Get Preview in Composable Functions That Depend on a View Model
Get Meta Data of Image - Android
Android Studio - Cannot Resolve Symbol 'Firebase'
How to Know If a Specific User Has Rated a Android App
How to Download Xml File from Server and Save It in Sd Card
Signing an APK with an Upload Key Provided by Google Play
How to Filter Listview Using Getfilter() in Baseadapter
Android - Activity Not Found Exception
Android M Write to Sd Card - Permission Denied
How to Add Firebase Database Rules Without Authentication
Android - Choose File Button in Webview
How to Highlight the Table Row on Click
How to Check If User Is Logged in with Fb Sdk 4.0 for Android
How to Animate a View in Android and Have It Stay in The New Position/Size
Listview: Textview with Linkmovementmethod Makes List Item Unclickable
What Is More Efficient? Static, Data Passing, Shared Preferences, Database...