Question

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?
Was it helpful?

Solution 3

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) {
    }
}

OTHER TIPS

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.

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();
}

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

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());

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

}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top