как использовать 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. как добавить другие поля в форму?

Примечание: этот ответ предназначен для 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(); 

Взгляните на примеры кодирования multipart / form-data, чтобы понять, как вам нужно создавать детали.

Когда у вас есть объект Multipart , все, что осталось сделать, это указать правильный заголовок Content-Type и передать байты тела запросу.

Поскольку вы, похоже, работаете с v2.0 API OkHttp, с которым у меня нет опыта, это всего лишь код угадывания:

 // 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 здесь приведенный код, который я использую, который адаптирован из fragmentа образца :

 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-формы)

Измените тип mime в соответствии с вашим файлом (здесь я предполагаю .csv) или сделаю его параметром для функции, если вы собираетесь загружать разные типы файлов

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

Примечание : поскольку это asynchronous вызов, тип логического возврата не указывает на успешную загрузку, а только на то, что запрос был отправлен в очередь 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, и файл будет загружен под именем «Файл».

PHP-сервер получит файлы

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

Я создал class OkHttp3 для 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); } }
  • Как разобрать JSON из Java HTTPResponse?
  • Попытка чтения с консоли в Java
  • Java SE 6 против JRE 1.6 против JDK 1.6 - Что это значит?
  • Можно ли вызвать метод main () classа из другого classа в java
  • Android HTML.fromHTML () с изображениями?
  • Запись PCM записанных данных в WAV-файл (java android)
  • Является ли законным вызывать метод запуска дважды в одной теме?
  • TimerTask vs Thread.sleep vs Handler postDelayed - наиболее точная функция вызова каждые N миллисекундов?
  • скопируйте 2d-массив в java
  • Что находится внутри пакета com.sun?
  • Как подключиться через HTTPS с помощью Jsoup?
  • Давайте будем гением компьютера.