如何使用okhttp上传文件?

use*_*372 35 java android okhttp mimecraft

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

如何使用它来发送带文件上传的http帖子请求?

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

}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 如何设置部件名称?在表单中,该文件应命名为file1.
  2. 如何在表单中添加其他字段?

iTe*_*ech 37

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

更改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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 注意:对于未解析的类名,请查看[link](http://stackoverflow.com/a/34676385/2304737) (10认同)

Bry*_*Kou 32

这是一个适用于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();
}
Run Code Online (Sandbox Code Playgroud)

  • `OkHttpClient 客户端 = new OkHttpClient();` (4认同)

ent*_*nto 17

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

Multipart来自mimecraft的类封装了整个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();
Run Code Online (Sandbox Code Playgroud)

查看多部分/表单数据编码的示例,以了解构建部件的方式.

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

既然您似乎正在使用我没有经验的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());
Run Code Online (Sandbox Code Playgroud)

对于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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @jawanam如果你正在使用OkHttp 3.x,那么OkHttp中已经包含了一个等效的类.有关其用法,请参阅[其他答案](http://stackoverflow.com/a/30498514/20226).这个答案中的`Mulitpart`是指[mimecraft](https://github.com/square/mimecraft)的. (2认同)