Как отправить фотографии на сервер с дополнительными полями в Android-приложении?

Я пытаюсь отправить несколько фотографий на сервер с помощью Retrofit. У меня есть конечная точка, как это:

@Multipart
@POST("/v1/props")
Call<ModelProp> createProp(
        @Header("x-auth") String token,
        @Part List<MultipartBody.Part> photo
);

Но я не знаю, как добавить к этому методу POST дополнительную информацию с помощью:

int price;
String currency;
ArrayList<String> tags;

Может ли кто-нибудь помочь мне добавить эти поля в POST с модификацией?

редактировать: Массив может содержать более 1000 элементов

вы можете добавить дополнительную информацию в строку запроса

namu 21.06.2019 18:36

Как я могу добавить массив в строку запроса? Есть ли способ?

Nastro 21.06.2019 18:37

когда вы делаете URL, вы можете добавить к нему параметр запроса. С сервера вам придется обрабатывать эти параметры. HttpUrl url = originalHttpUrl.newBuilder() .addQueryParameter("param1", "param1_value") .build();

namu 21.06.2019 18:50

см. [futurestud.io/tutorials/…

namu 21.06.2019 18:51

Спасибо за ваш совет, но если у меня есть 1000 элементов в массиве, не рекомендуется добавлять его в строку запроса.

Nastro 21.06.2019 18:57
1
5
71
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

В Retrofit 2 вы можете отправить ему дополнительные данные с изображением следующим образом:

Редактировать: На основе ответа Али Гафари вы также можете использовать PartMap

public interface ApiInterface {
    @Multipart
    @POST("/v1/props")
    Call<ModelProp> createProp(@Header("x-auth") String token, 
                      @Part List<MultipartBody.Part> photo,
                      @PartMap Map<String, RequestBody> map
}

Вы можете использовать его следующим образом:

List<MultipartBody.Part> parts = new ArrayList<>();    
for (int i=0; i < upFileList.size(); i++){
   parts.add(prepareFilePart("my_file["+i+"]", upFileList.get(i)));
}
Map<String, RequestBody> partMap = new HashMap<>();
partMap.put("price", createPartFromString(edtPrice.getText().toString()));
partMap.put("currency", createPartFromString(edtCurrency.getText().toString()));
partMap.put("tags", createPartFromString(new Gson().toJson(tagsArrayList));
Call<User> call = client.createProp(TokenUtils.getToken(this), partMap);
call.enqueue(new Callback<ModelProp>() {
    @Override
    public void onResponse(retrofit.Response<ModelProp> response, Retrofit retrofit) {
        // consume response
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
});

prepareFilePart метод

  private MultipartBody.Part prepareFilePart(String partName, Uri fileUri){

    File file = new File(fileUri.getPath(););

    RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);

    return MultipartBody.Part.createFormData(partName, file.getName(),requestBody);
  }

createPartFromString метод

public RequestBody createPartFromString(String string) {
        return RequestBody.create(MultipartBody.FORM, string);
    }

Похоже на правду, проверим кодом и отметим ответ. Спасибо!

Nastro 21.06.2019 19:14

откуда я могу получить метод getPath() в новом файле (getPath (fileUri))?

Nastro 22.06.2019 18:02
fileUri.getPath() - выдает ошибку при отказе: /external/images/media/63927 (Нет такого файла или каталога)
Nastro 22.06.2019 18:03

измените свой интерфейс на это:

@Multipart
@POST("/v1/props")
Call<ModelProp> createProp(
        @Header("x-auth") String token,
        @Part List<MultipartBody.Part> photo,
        @PartMap Map<String, RequestBody> map  //added

);


и используйте эти коды, чтобы получить карты и отправить их на createProp:

    public Map<String, RequestBody> getMap() {
        Map<String, RequestBody> partMap = new HashMap<>();
        String authorS = author.getText().toString();
        partMap.put("price", createPartFromString(price));

        // you can put more filed to partMap

        return partMap;
     }

 public RequestBody createPartFromString(String string) {
        return RequestBody.create(MultipartBody.FORM, string);
    }

Как добавить к этому массив?

Nastro 21.06.2019 19:14

Опция 1: Используйте несколько @Part и передавайте свои аргументы в обычном режиме.

@Multipart
@POST("/v1/props")
Call<ModelProp> createProp(
        @Header("x-auth") String token,
        @Part List<MultipartBody.Part> photo,
        @Part("price") int price,
        @Part("currency") String currency,
        @Part("tags") List<String> tags
);

Вариант 2: Используйте @PartMap и включите Map свои данные.

@Multipart
@POST("/v1/props")
Call<ModelProp> createProp(
        @Header("x-auth") String token,
        @Part List<MultipartBody.Part> photo,
        @PartMap Map<String, RequestBody> dataMap
);

и создайте карту данных для передачи

RequestBody price = ...
RequestBody currency = ...
RequestBody tags = ...

HashMap<String, RequestBody> map = new HashMap<>();  
map.put("price", description);  
map.put("currency", place);  
map.put("tags", time);

Другие вопросы по теме