Java 如何使用okhttp上传文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23512547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 23:28:43  来源:igfitidea点击:

how to use okhttp to upload a file?

javaandroidokhttpmimecraft

提问by user2219372

I use okhttp to be my httpclient. I think it's a good api but the doc is not so detailed.

我使用 okhttp 作为我的 httpclient。我认为这是一个很好的 api,但文档不是那么详细。

how to use it to make a http post request with file uploading?

如何使用它来发出带有文件上传的 http post 请求?

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?
  1. 如何设置零件名称?在表单中,该文件应命名为 file1。
  2. 如何在表单中添加其他字段?

采纳答案by ento

Note: this answer is for okhttp 1.x/2.x. For 3.x, see this other answer.

注意:此答案适用于 okhttp 1.x/2.x。对于 3.x,请参阅其他答案

The class Multipartfrom mimecraftencapsulates the whole HTTP body and can handle regular fields like so:

该类Multipartmimecraft封装整个HTTP体,可以处理普通的字段,如下所示:

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 encodingto get a sense of how you need to construct the parts.

查看多部分/表单数据编码的示例,以了解您需要如何构建这些部分。

Once you have a Multipartobject, all that's left to do is specify the right Content-Typeheader and pass on the body bytes to the request.

一旦有了Multipart对象,剩下要做的就是指定正确的Content-Type标头并将正文字节传递给请求。

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:

由于您似乎正在使用我没有经验的 OkHttp API 的 v2.0,因此这只是猜测代码:

// 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:

对于 OkHttp 1.5.4,这是我正在使用的精简代码,该代码改编自示例片段

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

回答by iTech

Here is a basic function that uses okhttp to upload a file and some arbitrary field (it literally simulates a regular HTML form submission)

这是一个使用 okhttp 上传文件和一些任意字段的基本功能(它实际上模拟了常规的 HTML 表单提交)

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

更改 mime 类型以匹配您的文件(这里我假设为 .csv),或者如果您要上传不同的文件类型,则将其作为函数的参数

  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 notindicate successful upload but only that the request was submitted to okhttp queue.

:因为它是异步调用,布尔返回类型并没有表明上传成功,但只请求被提交给okhttp队列。

回答by Bryant Kou

Here's an answer that works with OkHttp 3.2.0:

这是适用于 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();
}

回答by Kasim Rangwala

I've created cool helper class for OkHttp3. it here

我为OkHttp3. 在这里

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

回答by Vignesh KM

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".

上面的代码将用户名、密码作为post参数发送,文件将以“文件”的名称上传。

PHP Server will receive the files

PHP 服务器将接收文件

    if (isset($_FILES["File"]) &&
        isset($_POST['username']) &&
        isset($_POST['password'])) {
        //All Values found
    }else{
        echo 'please send the required data';
    }

回答by Narahari Gugulothu

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