如何使用okhttp上传文件?

我使用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. 如何在表单中添加其他字段?

Solutions Collecting From Web of "如何使用okhttp上传文件?"

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

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

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

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

既然您似乎正在使用我没有经验的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,这里是一个我正在使用的精简代码,它是从一个示例代码段改编而来的 :

 OkHttpClient client = new OkHttpClient(); OutputStream out = null; try { URL url = new URL("http://www.example.com"); HttpURLConnection connection = client.open(url); for (Map.Entry 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) { } } 

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

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

  public static Boolean uploadFile(String serverURL, File file) { try { RequestBody requestBody = new MultipartBuilder() .type(MultipartBuilder.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(Request request, IOException e) { // Handle the error } @Override public void onResponse(Response response) throws IOException { if (!response.isSuccessful()) { // Handle the error } // Upload successful } }); return true; } catch (Exception ex) { // Handle the error } return false; } 

注意 :因为它是异步调用,所以布尔返回types不表示成功上载,而只是请求已提交给okhttp队列。

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

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

PHP Server将接收文件

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

我为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; } /** * Uses:
*

* {@code * ArrayMap formField = new ArrayMap<>();} *
* {@code formField.put("key1", "value1");}
* {@code formField.put("key2", "value2");}
* {@code formField.put("key3", "value3");}
*
* {@code String response = helper.postToServer("http://www.example.com/", formField);}
*

* * @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 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 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(); } /** * Uses:
*

* {@code * ArrayMap formField = new ArrayMap<>();} *
* {@code formField.put("key1", "value1");}
* {@code formField.put("key2", "value2");}
* {@code formField.put("key3", "value3");}
*
* {@code * ArrayMap
filePart = new ArrayMap<>();} *
* {@code filePart.put("key1", new File("pathname"));}
* {@code filePart.put("key2", new File("pathname"));}
* {@code filePart.put("key3", new File("pathname"));}
*
* {@code String response = helper.postToServer("http://www.example.com/", formField, filePart);}
*

* * @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
formField, @Nullable ArrayMap 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 entry : formField.entrySet()) { multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue()); } } if (filePart != null) { for (Map.Entry 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); } }