Android и Retrofit2 — отправка файла изображения в составном запросе

#android #image-uploading #retrofit2

#Android #загрузка изображения #retrofit2

Вопрос:

Я создаю приложение, в котором мне нужно отправить изображение из галереи на сервер.

Это должны быть заголовки (в соответствии с apiary).

 Content-Type:image/jpeg
X-Filename:photo.jpg
  

Но в журналах в interceptor есть только X-Filename, хотя я пробовал несколько способов, и у меня заканчиваются идеи.

Сервер отвечает 200, но следующий вызов (фиксация изображения) возвращает 500 с ошибкой в конце публикации.

Это методы:

     @Multipart
    @POST("uploads")
    Observable<String> uploadImage(
        @Header("Content-Type") String contentType,
        @Header("X-Filename") String fileName,
        @Header("Authorization") String token,
        @Part MultipartBody.Part file
    );

    @GET("uploads/{fileId}/commit")
    Observable<String> commitFile(
        @Header("Content-Type") String type,
        @Header("Authorization") String token,
        @Path("fileId") String fileId
    );
  

Клиент OkHttp:

   private OkHttpClient createApiClient(Context context) {
      int cacheSize = 10 * 1024 * 1024; // 10 MiB
      Cache cache = new Cache(context.getCacheDir(), cacheSize);

      OkHttpClient.Builder builder = new OkHttpClient.Builder();
      builder.addInterceptor(chain -> {
          Request request = chain.request().newBuilder().build();
          request.newBuilder().addHeader("Content-Type", "application/json");
          Timber.d("Request: [%s] %s", request.method(), request.url());
          Timber.d("Request: %s", request.headers().toString());
          if (request.body() != null) {
              Timber.d("Request: %s", request.body().toString());
          }
          return chain.proceed(request);
      });
      builder.cache(cache);
      return builder.build();
  }
  

Результирующие журналы:

 D/NetModule: Request: [POST] https://winged-guild-133523.appspot.com/api/v1/uploads
D/NetModule: Request: X-Filename: asura.png
                      Authorization: HAYVi3clcqjug53IPS6AYMgzCPGnDE3Si
D/NetModule: Request: retrofit2.RequestBuilder$ContentTypeOverridingRequestBody@7c37f46
  

То же самое происходит с Postman — Скриншот Postman

Сбой фиксации с этой ошибкой: (извините за уродливое форматирование)

     {
        "errorCode": "ImagesServiceFailureException",
        "errorParam": "",
        "errorMessage":"com.google.appengine.api.images.ImagesServiceFailureException: "
}
  

Как я уже сказал, у меня заканчиваются идеи, и я был бы очень признателен за любую помощь в решении этой проблемы с загрузкой.

(редактировать) PS: опустив строку @Header («Content-Type») ContentType в приложении и используя application / x-www-form-urlencoded в Postman, загрузка изображения и фиксация проходят успешно, но изображение по возвращаемому URL не содержит метаданных и, следовательно, не может быть отображено.

Ответ №1:

Не используйте @Multipart . Вместо этого используйте что-то вроде этого:

  @POST("upload/image")   
 Observable<ResponseBody> uploadImage(@Body RequestBody body);

 File imageFile = new File(path);   
 RequestBody body =  RequestBody.create(MediaType.parse("image/jpeg"),imageFile);

 api.uploadImage(body);
  

Комментарии:

1. Спасибо. Что имело значение для меня, так это возможность указать тип файла, изменив "image/*" на "image/jpeg" .

Ответ №2:

Это мой код, использующий retrofit

 @Multipart
    @POST(ServiceConfig.API_CREATE_DEPENDENT_ACCOUNT)
    @Headers({
            "Accept: application/json",
            "Accept-Encoding: gzip"
    })
    Call<DataResponse<CreateDependentAccountResponse>>  createDependentAccount(@Query(JioConstants.ParamQuery.TOKEN) String token,
                                                                              @Query(JioConstants.ParamQuery.USER_ID) long userID,
                                                                              @Query(JioConstants.ParamQuery.FIRST_NAME) String firstName,
                                                                              @Query(JioConstants.ParamQuery.LAST_NAME) String lastName,
                                                                              @Query(JioConstants.ParamQuery.GENDER) String gender,
                                                                              @Query(JioConstants.ParamQuery.DOB) String dob,
                                                                              @Query(JioConstants.ParamQuery.RELATIONSHIP_ID) long relationshipID,
                                                                              @Query(JioConstants.ParamQuery.DISPLAY_UNIT) String displayUnit,
                                                                              @Part("avatar"; filename="picture.jpg" ") RequestBody file);
  

и

 RequestBody file = null;
        if (mFileTemp != null) {
            file = RequestBody.create(MediaType.parse("image/*"), mFileTemp);
        } else {
            file = RequestBody.create(MediaType.parse("image/*"), "");
        }

        manageCall(ServiceManager.INSTANCE2().
                createDependentAccount(token, userID, firstName, lastName, gender, dob, relationshipID, displayUnit, file))
                .enqueue(new SimplifiedCallback<CreateDependentAccountResponse>() {

                    @Override
                    public void success(CreateDependentAccountResponse data, String message) {
                        hideLoading();
  

Удачи. Это моя игра