如何使用okhttp上传文件?

时间:2014-05-07 08:25:47

标签: 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();

}

我的问题是:

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

6 个答案:

答案 0 :(得分:32)

这是一个使用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;
}

注意:因为它是异步调用,布尔返回类型表示上传成功,但只是请求已提交给okhttp队列。

答案 1 :(得分:27)

这是一个适用于OkHttp 3.2.0的答案:

public void upload(String url, File file) throws IOException {
    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 = this.client.newCall(request).execute();
}

答案 2 :(得分:15)

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

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

查看examples of multipart/form-data encoding,了解您需要如何构建零件。

一旦你有一个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());

对于OkHttp 1.5.4,这是一个我正在使用的精简代码,它改编自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) {
    }
}

答案 3 :(得分:3)

$("td").css({'padding':'8px 2px'});

上面的代码会发送用户名,密码作为post参数,文件将以&#34; File&#34;的名义上传。

PHP Server将收到文件

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

用于将任何文件以及文件元数据轻松上传到Google驱动器的完美代码。

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