how to use okhttp to upload a file?
Solution 1
Note: this answer is for okhttp 1.x/2.x. For 3.x, see this other answer.
The class Multipart
from mimecraft encapsulates the whole HTTP body and can handle regular fields like so:
Multipart m = new Multipart.Builder()
.type(Multipart.Type.FORM)
.addPart(new Part.Builder()
.body("value")
.contentDisposition("form-data; name=\"non_file_field\"")
.build())
.addPart(new Part.Builder()
.contentType("text/csv")
.body(aFile)
.contentDisposition("form-data; name=\"file_field\"; filename=\"file1\"")
.build())
.build();
Take a look at examples of multipart/form-data encoding to get a sense of how you need to construct the parts.
Once you have a Multipart
object, all that's left to do is specify the right Content-Type
header and pass on the body bytes to the request.
Since you seem to be working with the v2.0 of the OkHttp API, which I don't have experience with, this is just guess code:
// You'll probably need to change the MediaType to use the Content-Type
// from the multipart object
Request.Body body = Request.Body.create(
MediaType.parse(m.getHeaders().get("Content-Type")),
out.toByteArray());
For OkHttp 1.5.4, here is a stripped down code I'm using which is adapted from a sample snippet:
OkHttpClient client = new OkHttpClient();
OutputStream out = null;
try {
URL url = new URL("http://www.example.com");
HttpURLConnection connection = client.open(url);
for (Map.Entry<String, String> entry : multipart.getHeaders().entrySet()) {
connection.addRequestProperty(entry.getKey(), entry.getValue());
}
connection.setRequestMethod("POST");
// Write the request.
out = connection.getOutputStream();
multipart.writeBodyTo(out);
out.close();
// Read the response.
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Unexpected HTTP response: "
+ connection.getResponseCode() + " " + connection.getResponseMessage());
}
} finally {
// Clean up.
try {
if (out != null) out.close();
} catch (Exception e) {
}
}
Solution 2
Here is a basic function that uses okhttp to upload a file and some arbitrary field (it literally simulates a regular HTML form submission)
Change the mime type to match your file (here I am assuming .csv) or make it a parameter to the function if you are going to upload different file types
public static Boolean uploadFile(String serverURL, File file) {
try {
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/csv"), file))
.addFormDataPart("some-field", "some-value")
.build();
Request request = new Request.Builder()
.url(serverURL)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Call call, final IOException e) {
// Handle the error
}
@Override
public void onResponse(final Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
// Handle the error
}
// Upload successful
}
});
return true;
} catch (Exception ex) {
// Handle the error
}
return false;
}
Note: because it is async call, the boolean return type does not indicate successful upload but only that the request was submitted to okhttp queue.
Solution 3
Here's an answer that works with OkHttp 3.2.0:
public void upload(String url, File file) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/plain"), file))
.addFormDataPart("other_field", "other_field_value")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
Response response = client.newCall(request).execute();
}
Solution 4
I've created cool helper class for OkHttp3
. it here
public class OkHttp3Helper {
public static final String TAG;
private static final okhttp3.OkHttpClient client;
static {
TAG = OkHttp3Helper.class.getSimpleName();
client = new okhttp3.OkHttpClient.Builder()
.readTimeout(7, TimeUnit.MINUTES)
.writeTimeout(7, TimeUnit.MINUTES)
.build();
}
private Context context;
public OkHttp3Helper(Context context) {
this.context = context;
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {@code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {@code formField.put("key1", "value1");}<br/>
* {@code formField.put("key2", "value2");}<br/>
* {@code formField.put("key3", "value3");}<br/>
* <br/>
* {@code String response = helper.postToServer("http://www.example.com/", formField);}<br/>
* </p>
*
* @param url String
* @param formField android.support.v4.util.ArrayMap
* @return response from server in String format
* @throws Exception
*/
@NonNull
public String postToServer(@NonNull String url, @Nullable ArrayMap<String, String> formField)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null) {
okhttp3.FormBody.Builder formBodyBuilder = new okhttp3.FormBody.Builder();
for (Map.Entry<String, String> entry : formField.entrySet()) {
formBodyBuilder.add(entry.getKey(), entry.getValue());
}
requestBuilder.post(formBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {@code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {@code formField.put("key1", "value1");}<br/>
* {@code formField.put("key2", "value2");}<br/>
* {@code formField.put("key3", "value3");}<br/>
* <br/>
* {@code
* ArrayMap<String, File> filePart = new ArrayMap<>();}
* <br/>
* {@code filePart.put("key1", new File("pathname"));}<br/>
* {@code filePart.put("key2", new File("pathname"));}<br/>
* {@code filePart.put("key3", new File("pathname"));}<br/>
* <br/>
* {@code String response = helper.postToServer("http://www.example.com/", formField, filePart);}<br/>
* </p>
*
* @param url String
* @param formField android.support.v4.util.ArrayMap
* @param filePart android.support.v4.util.ArrayMap
* @return response from server in String format
* @throws Exception
*/
@NonNull
public String postMultiPartToServer(@NonNull String url,
@Nullable ArrayMap<String, String> formField,
@Nullable ArrayMap<String, File> filePart)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null || filePart != null) {
okhttp3.MultipartBody.Builder multipartBodyBuilder = new okhttp3.MultipartBody.Builder();
multipartBodyBuilder.setType(okhttp3.MultipartBody.FORM);
if (formField != null) {
for (Map.Entry<String, String> entry : formField.entrySet()) {
multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
}
}
if (filePart != null) {
for (Map.Entry<String, File> entry : filePart.entrySet()) {
File file = entry.getValue();
multipartBodyBuilder.addFormDataPart(
entry.getKey(),
file.getName(),
okhttp3.RequestBody.create(getMediaType(file.toURI()), file)
);
}
}
requestBuilder.post(multipartBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
private okhttp3.MediaType getMediaType(URI uri1) {
Uri uri = Uri.parse(uri1.toString());
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = context.getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return okhttp3.MediaType.parse(mimeType);
}
}
Solution 5
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(180, TimeUnit.SECONDS).readTimeout(180, TimeUnit.SECONDS).build();
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("File", path.getName(),RequestBody.create(MediaType.parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),path))
.addFormDataPart("username", username)
.addFormDataPart("password", password)
.build();
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
result = response.body().string();
Above code will send the username, password as the post parameter and the file will be uploaded in the name of "File".
PHP Server will receive the files
if (isset($_FILES["File"]) &&
isset($_POST['username']) &&
isset($_POST['password'])) {
//All Values found
}else{
echo 'please send the required data';
}
user2219372
Updated on July 14, 2022Comments
-
user2219372 almost 2 years
I use okhttp to be my httpclient. I think it's a good api but the doc is not so detailed.
how to use it to make a http post request with file uploading?
public Multipart createMultiPart(File file){ Part part = (Part) new Part.Builder().contentType("").body(new File("1.png")).build(); //how to set part name? Multipart m = new Multipart.Builder().addPart(part).build(); return m; } public String postWithFiles(String url,Multipart m) throws IOException{ ByteArrayOutputStream out = new ByteArrayOutputStream(); m.writeBodyTo(out) ; Request.Body body = Request.Body.create(MediaType.parse("application/x-www-form-urlencoded"), out.toByteArray()); Request req = new Request.Builder().url(url).post(body).build(); return client.newCall(req).execute().body().string(); }
my question is:
- how to set part name? in the form, the file should be named file1.
- how to add other fields in the form?
-
user2219372 almost 10 yearsIt worked by changing " Request.Body body = Request.Body.create(MediaType.parse("application/x-www-form-urlencoded"), out.toByteArray());" to "Request.Body.create(MediaType.parse(m.getHeaders().get("Content-Type"))"
-
ento almost 10 yearsThanks for the follow-up!
-
Admin over 8 yearswhat dependency should I add for
Multipart
? -
ento over 8 years@jawanam If you're using OkHttp 3.x, then an equivalent class is already included in OkHttp. See the other answer for its usage. The
Mulitpart
in this answer refers to mimecraft's. -
zygimantus over 8 yearsDoes it add Content-Length header automatically?
-
mr5 over 8 yearsNote: For unresolved class names, check this link
-
Stephen Hosking over 7 yearsI've spent two days trying to upload a file from Android to an Asp.Net MVC HttpPost action method. The other, more basic, java solutions made the connection but failed with the file upload - and were almost impossible to debug. This was the solution that finally worked!
-
Stephen Hosking over 7 yearsBUT, when I upgraded okhttp to 3.5.0 it no longer compiled. See comment above by mr5 for resolving links, and answer below by @Bryant Kou for changed class names.
-
ban-geoengineering almost 7 years
OkHttpClient client = new OkHttpClient();
-
Elletlar over 5 yearsWelcome to Stack Overflow. While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. How to Answer
-
Serg Burlaka about 5 yearsthis answer is to old
-
Ahmad over 4 yearswhere you use
text/csv
What will i use for mp3 file or jpg ? is there any random or auto method which work on all type of files ?