how to use okhttp to upload a file?

JavaAndroidOkhttpMimecraft

Java Problem Overview


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:

  1. how to set part name? in the form, the file should be named file1.
  2. how to add other fields in the form?

Java Solutions


Solution 1 - Java

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 2 - Java

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 3 - Java

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 4 - Java

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 - Java

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';
    }

Solution 6 - Java

Perfect code for uploading any files to google drive along with metadata of files easily.

    String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");

    //String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable");
    boolean status;
    String metaDataFile = "{\"title\":\"" + step.getFile_name() + "\"," +
            "\"description\":\"" + step.getDescription() + "\"," +
            "\"parents\":[{\"id\":\"" + step.getFolderId() + "\"}]," +
            "\"capabilities\":{\"canEdit\":\"" + false + "\", \"canDownload\":\" "+ false +" \" }, " +
            "\"type\":\"" + step.getFile_access() + "\"" +
            "}";
    
    //get the encoded byte data for decode
    byte[] file = Base64.decodeBase64(step.getFile_data());
    
    //attaching metadata to our request object
    RequestBody requestBodyMetaData = RequestBody.create(MediaType.parse("application/json"), metaDataFile);
    
    //passing both meta data and file content for uploading
    RequestBody requestBodyMultipart = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("metadata", null, requestBodyMetaData)
            .addFormDataPart("file", null, RequestBody.create(MediaType.parse("application/octet-stream"), file))
            .build();
    Request request = new Request.Builder()
            .url(url)
            .addHeader("Authorization", String.format("Bearer %s", step.getAccess_token()))
            .post(requestBodyMultipart)
            .build();
    
    OkHttpClient okHttpClient = new OkHttpClient();
    
    try {
        // Get response after rest call.
        Response response = okHttpClient.newCall(request).execute();
        status = response.code() == 200 ? true : false;
        map.put(step.getOutput_variable(), response.code());

Solution 7 - Java

Asynchronously ...

public void UploadFileFromOkhttp(String filePath, String jwtToken){
String url = "https://api.baserow.io/api/user-files/upload-file/";
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
File file = new File(filePath);
builder.addFormDataPart("file" , file.getName() , RequestBody.create(MediaType.parse("image/*"), file));
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
        .url(url)
        .addHeader("Authorization", "JWT "+ jwtToken)
        .post(requestBody)
        .build();
okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
  @Override
  public void onFailure(@NotNull Call call, @NotNull IOException e) {
    activity.runOnUiThread(new Runnable() {
      @Override
      public void run() {
        OnError(e.getMessage());
      }
    });
  }

  @Override
  public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
      final String responseData = response.body().string();
      activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          OnSuccess(responseData);
        }
      });
  }
});

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2219372View Question on Stackoverflow
Solution 1 - JavaiTechView Answer on Stackoverflow
Solution 2 - JavaBryant KouView Answer on Stackoverflow
Solution 3 - JavaentoView Answer on Stackoverflow
Solution 4 - JavaKasim RangwalaView Answer on Stackoverflow
Solution 5 - JavaVignesh KMView Answer on Stackoverflow
Solution 6 - JavaNarahari GugulothuView Answer on Stackoverflow
Solution 7 - JavaOseamiyaView Answer on Stackoverflow