What are my options for uploading a single large file (more specifically, to s3) in multipart in Android using OKhttp?
-
2can you please update with the used code to solve this issue? – StErMi Oct 06 '14 at 14:25
-
1You can follow this one also http://stackoverflow.com/a/34037063/1318946 – Pratik Butani Dec 02 '15 at 07:28
-
1None of these solutions handle a 'large' file. Please delete them all so that a real solution can be documented. – behelit Dec 03 '21 at 08:17
5 Answers
Get OkHttp 2.1, and use MultipartBuilder.addFormDataPart()
which takes the filename as a parameter.
/**
* Upload Image
*
* @param memberId
* @param sourceImageFile
* @return
*/
public static JSONObject uploadImage(String memberId, String sourceImageFile) {
try {
File sourceFile = new File(sourceImageFile);
Log.d(TAG, "File...::::" + sourceFile + " : " + sourceFile.exists());
//Determining the media type
final MediaType MEDIA_TYPE = sourceImageFile.endsWith("png") ?
MediaType.parse("image/png") : MediaType.parse("image/jpeg");
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("member_id", memberId)
.addFormDataPart("file", "profile.png", RequestBody.create(MEDIA_TYPE, sourceFile))
.build();
Request request = new Request.Builder()
.url(URL_UPLOAD_IMAGE)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
return new JSONObject(response.body().string());
} catch (UnknownHostException | UnsupportedEncodingException e) {
Log.e(TAG, "Error: " + e.getLocalizedMessage());
} catch (Exception e) {
Log.e(TAG, "Other Error: " + e.getLocalizedMessage());
}
return null;
}
#Edited for okhttp3:
compile 'com.squareup.okhttp3:okhttp:3.4.1'
RequestBody replaced by:
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("uploaded_file", filename, RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.addFormDataPart("result", "my_image")
.build();
#Uploaded Demo on GITHUB: ##I have added my answer for Multiple Image Upload :)

- 379
- 5
- 16

- 60,504
- 58
- 273
- 437
-
@Pratik Butani It works but i want to read response from API. I have to do another task based on response. – moDev Dec 21 '15 at 08:50
-
-
I am using enqueue method instead of execute. Can we send multiple images through multipart?? – moDev Dec 21 '15 at 12:45
-
-
I got the answer too regarding multiple images. Still i don't see the response from API instead it throws okHttpResponse. – moDev Dec 21 '15 at 14:24
-
-
-
1
-
-
1
-
Thanks Pratik. I did it yesterday.Thanks a lot :-). It worked – Priyanka Singhal Oct 11 '19 at 05:31
-
Is Multipart the one that makes uploading a large file possible? I am using RequestBody and seems like I am unable to upload a very large file. – abhiarora Jan 29 '22 at 17:34
-
To deal with large files use the Okio library. I provided an example here https://stackoverflow.com/a/68481022/2807177 – gmanjon Jan 31 '22 at 12:25
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.

- 39,078
- 8
- 121
- 128
-
Thanks Jesse. Is there any way to track progress of the request assuming I know the content length? – Tomer Weller Jun 18 '14 at 13:29
-
6@TomerWeller you can create a custom RequestBody that tracks bytes moved. You'll want to wrap the Sink passed to the RequestBody. – Jesse Wilson Jun 19 '14 at 04:27
-
1Tomer, see my answer here: http://stackoverflow.com/questions/25962595/tracking-progress-of-multipart-file-upload-using-okhttp/26376724#26376724 – Eduard B. Oct 15 '14 at 07:38
-
If I have the image in byte[] I tried doing this: `addPart(Headers.of("..."), RequestBody.create(MEDIA_TYPE_PNG, imageBytes))`; But this doesn't work. It puts the byte data in the headers instead of the body. Any idea why? – b.lyte Mar 24 '15 at 18:18
-
1I figured it out. With imgur, you don't have to provide a filename, so sending the image bytes like I did in the above comment worked. However, for the API I'm actually talking to, it expects a filename so this worked: `multipartBuilder.addFormDataPart("image", fileName, entry.getValue());` – b.lyte Mar 24 '15 at 18:40
-
That is great, but you can also add the attributes to POST more easily using: .addFormDataPart("file", "profile.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile)) and .addFormDataPart("id", "1") for string attribute – sandino Jan 14 '16 at 13:52
-
5MultiPartBuilder is called MultipartBody.Builder now, see: http://stackoverflow.com/questions/34676044/multipartbuilder-cant-be-resolved-in-okhttp3-0-0-rc1 – Warpzit May 31 '16 at 05:22
-
Hi buddies, for uploading image is it good to use asynchronous or not? you know, I don't understand what is the difference between asynchronous and synchronous.... – jsina Jun 18 '16 at 10:04
-
Hi guys, please answer this question I am struck here https://stackoverflow.com/questions/52520520/how-to-add-list-of-object-i-e-userdata-type-to-multipartbody-in-okhttpclient – Rahul Sep 27 '18 at 06:00
-
1The link is broken to recipe page. Here is the link: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PostMultipart.java – Jatin Mar 01 '21 at 04:02
-
-
To deal with large files and `RequestBody` use the Okio library. I provided an example here https://stackoverflow.com/a/68481022/2807177 – gmanjon Jan 31 '22 at 12:25
For okhttp 4.* use the MultipartBody.Builder
:
fun postMultipart(url: String, text: String, imagePath: String, imageFileName: String): okhttp3.Response? {
val file = File(imagePath)
val fileRequestBody = file.asRequestBody("image/jpeg".toMediaType())
val requestBody = MultipartBody.Builder()
.addFormDataPart("text", text)
.addFormDataPart("image", imageFileName, fileRequestBody)
.build()
val request = getRequestBuilder(url)
.post(requestBody)
.build()
val client = OkHttpClient()
client.newCall(request).execute().use { response ->
return response
}
}

- 2,583
- 1
- 30
- 40
-
Is `Multipart` the one that makes uploading a large file possible? I am using `RequestBody` and seems like I am unable to upload a very large file. – abhiarora Jan 27 '22 at 18:36
-
To deal with large files use the Okio library. I provided an example here https://stackoverflow.com/a/68481022/2807177 – gmanjon Jan 31 '22 at 12:25
for okhttp 2.6.0 {
try {
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/xxx/share/" + "ic_launcher.png");
String contentType = file.toURL().openConnection().getContentType();
RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), file);
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("fileUploadType","1")
.addFormDataPart("miniType",contentType)
.addFormDataPart("ext",file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf(".")))
.addFormDataPart("fileTypeName","img")
.addFormDataPart("Filedata","ss.png",fileBody)
.build();
Request request = new Request.Builder()
.url(Contains.MULTIPARTY_POST)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tvGetNews.setText("upload fail");
}
});
}
@Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
tvGetNews.setText("upload success");
}
});
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

- 7,283
- 2
- 11
- 6
-
Is `Multipart` the one that makes uploading a large file possible? I am using `RequestBody` and seems like I am unable to upload a very large file. – abhiarora Jan 27 '22 at 18:37
-
To deal with large files and `RequestBody` use the Okio library. I provided an example here https://stackoverflow.com/a/68481022/2807177 – gmanjon Jan 31 '22 at 12:26
In Android you usally part from an Uri
. The problem when using large files is that you easily run into OutOfMemoryError
if you try to read the full stream to a byte array (everything in memory) or you end up creating useless files with Uri stream. This is because RequestBody
doesn't support creation from Stream
(because sometimes OkHttp needs to read it many times, if you get a 30X redirect for instance) or Uri
(because OkHttp is not an Android library).
But OkHttp provides the library Okio, with convenient classes emulating Streams (Source
and Sink
) and more convenient internal usage.
So, to create a BodyRequest
form an Uri
avoiding any OutOfMemoryError
due to large files create it this way:
private static final MediaType MULTIPART_FOR_DATA = MediaType.parse("multipart/form-data");
private @NotNull RequestBody getFilePart(Uri largeFileUri) {
return new RequestBody() {
@Override
public MediaType contentType() {
return MULTIPART_FOR_DATA;
}
@Override
public void writeTo(@NotNull BufferedSink sink) throws IOException {
try (Source source = Okio.source(context.getContentResolver().openInputStream(mediaUri))) {
sink.writeAll(source);
}
}
};
}
Thank you to everyone posting and commenting in the folowing GitHub thread https://github.com/square/okhttp/issues/3585

- 1,483
- 1
- 12
- 16