загрузить фото с модификацией2: модификация: 2.0.0-beta4

У меня проблема с загрузкой фото на сервер с использованием модификации 2. Может ли кто-нибудь мне помочь? что я сделал не так? мой внутренний разработчик огорчил меня тем, что граница в заголовке не сгенерирована =( это мой интерфейс:

import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.Call;
import retrofit2.http.Multipart;
import okhttp3.MultipartBody;
import com.google.gson.JsonElement;

public interface Retrofitv2Api {
    @Multipart
    @Headers("Content-Type: multipart/form-data;")
    @POST("/mobile/v1/classifieds/UploadImage")
    Call<JsonElement> UploadImage(@Part MultipartBody.Part body,@Part("uniqId")String uniqId,@Part("token")String token);}

строитель:

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitV2Config {
    private  static Retrofit getRetrofit(){
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://api.qrz.ru")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
        return retrofit;
    }

    public static Retrofitv2Api getService(){
        return getRetrofit().create(Retrofitv2Api.class);
    }

и загрузить фрагмент:

String photoPath = photoAdapter.getPhotoPaths().get(0);
                File image = new File(photoPath);


                RequestBody imageBody = RequestBody.create(MediaType.parse("image/*"), image);

                MultipartBody.Part body =  MultipartBody.Part.createFormData("file", image.getName(), imageBody);


                RetrofitV2Config.getService().UploadImage(body , "2536654", Token.getSavedToken()).enqueue(new Callback<JsonElement>() {
                    @Override
                    public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                        Log.i(Logger.TAG, "onResponseUpload " + response.body() + " " + response.code());
                    }

                    @Override
                    public void onFailure(Call<JsonElement> call, Throwable t) {
                        Log.i(Logger.TAG, "onFailureUpload");
                    }
                });

бэкенд ответ:

21:34:32.386117 IP 46.37.203.69.50461 > 62.181.46.35.http: Flags [P.], seq 1184070465:1184071311, ack 3418438796, win 65535, length 846
[email protected]....%.E>..#...PF.{A..<.P...]...POST /mobile/v1/classifieds/UploadImage HTTP/1.1
Content-Type: multipart/form-data
Content-Length: 647
Host: api.qrz.ru
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.2.0

--950f42dd-12a1-4e11-a3b0-826ddaf41aa3
Content-Disposition: form-data; name="img"
Content-Transfer-Encoding: binary
Content-Type: application/json; charset=UTF-8
Content-Length: 2

{}
--950f42dd-12a1-4e11-a3b0-826ddaf41aa3
Content-Disposition: form-data; name="uniqId"
Content-Transfer-Encoding: binary
Content-Type: application/json; charset=UTF-8
Content-Length: 8

"215132"
--950f42dd-12a1-4e11-a3b0-826ddaf41aa3
Content-Disposition: form-data; name="token"
Content-Transfer-Encoding: binary
Content-Type: application/json; charset=UTF-8
Content-Length: 22

person Mazda Doc    schedule 28.03.2016    source источник
comment
Пожалуйста, прочтите stackoverflow.com/questions/36491096/   -  person BNK    schedule 12.04.2016


Ответы (4)


Спасибо вам всем ! Я нахожу решение. В моем случае я должен использовать MultipartBody.Part вместо String в интерфейсе Retrofitv2Api

public interface Retrofitv2Api {
@Multipart
@POST("/mobile/v1/classifieds/UploadImage")
Call<UploadPhoto> UploadImage(@Part MultipartBody.Part body,@Part MultipartBody.Part uniqId,@Part MultipartBody.Part token);}

File image = new File(path);

        RequestBody imageBody = RequestBody.create(MediaType.parse("image/jpeg"), image);

        MultipartBody.Part body = MultipartBody.Part.createFormData("img", image.getName(), imageBody);
        MultipartBody.Part uniqID = MultipartBody.Part.createFormData("uniqId", uniqId);
        MultipartBody.Part token = MultipartBody.Part.createFormData("token", Token.getSavedToken());

        Call<UploadPhoto> call = RetrofitV2Config.getService().UploadImage(body, uniqID, token);
        call.enqueue(new Callback<UploadPhoto>() {
            @Override
            public void onResponse(Call<UploadPhoto> call,
                                   Response<UploadPhoto> response) {
                Log.v("Upload", "success: " + response.raw().toString());

            }

            @Override
            public void onFailure(Call<UploadPhoto> call, Throwable t) {
                Log.e("Upload error:", t.getMessage());

            }
        });
person Mazda Doc    schedule 21.04.2016

Попробуйте использовать TypedFile вместо MultipartBody, например:

String photoPath = photoAdapter.getPhotoPaths().get(0);
  try {
        File image = new File(getApplicationContext().getFilesDir().getPath().toString(), "YourFileName");

        // Decode with inSampleSize 
        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
        bitmapOptions.inSampleSize = calculateInSampleSize(bitmapOptions, 1080, 1080);
        bitmapOptions.inJustDecodeBounds = false;

        Bitmap bitmap = BitmapFactory.decodeFile(photoPath, bitmapOptions);

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);
            byte[] bitmapdata = bos.toByteArray();

            //write the bytes in file
            FileOutputStream fos = new FileOutputStream(image);
            fos.write(bitmapdata);
            fos.flush();
            fos.close();

                // yourImageType means for example .png .jpg etc.
                TypedFile typedFile = new TypedFile("image/yourImageType", image);

      } catch (IOException e) {
      } catch (OutOfMemoryError outOfMemoryError) {
      }


     RetrofitV2Config.getService().UploadImage(typedFile , "2536654", Token.getSavedToken()).enqueue(new Callback<JsonElement>() {
        @Override
        public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
            Log.i(Logger.TAG, "onResponseUpload " + response.body() + " " + response.code());
        }

        @Override
        public void onFailure(Call<JsonElement> call, Throwable t) {
            Log.i(Logger.TAG, "onFailureUpload");
        }
    });

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

   @Multipart
    @Headers("Content-Type: multipart/form-data;")
    @POST("/mobile/v1/classifieds/UploadImage")
    Call<JsonElement> UploadImage(@Part("file") TypedFile file,@Part("uniqId")String uniqId,@Part("token")String token);}
person Ivan Ivanov    schedule 28.03.2016

public interface UploadAvatarService {
    @Multipart
    @POST("user/upload_head")
    Observable<UploadAvatarBean> upload(@Part("file\"; filename=\"image.png\"") RequestBody avatarFile);
}

Part будет кодироваться в Retrofit как

Headers headers =
              Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
                  "Content-Transfer-Encoding", part.encoding());

вам нужно установить имя файла в файл.

person cs x    schedule 12.04.2016

Вы должны использовать RequestBody вместо String

public interface Retrofitv2Api {
@Multipart
@Headers("Content-Type: multipart/form-data;")
@POST("/mobile/v1/classifieds/UploadImage")
Call<JsonElement> UploadImage(@Part MultipartBody.Part body,@Part("uniqId")RequestBody uniqId,@Part("token") RequestBody token);
}


private void UploadImage(File file,String uniqId,String token) {  
// create upload service client
Retrofitv2Api service =
        new RetrofitV2Config().getService();

RequestBody requestFile =
        RequestBody.create(MediaType.parse("multipart/form-data"), file);

// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
        MultipartBody.Part.createFormData("file", file.getName(), requestFile);


// finally, execute the request
Call<ResponseBody> call = service.upload( body,RequestBody.create(
                MediaType.parse("multipart/form-data"), uniqId),RequestBody.create(
                MediaType.parse("multipart/form-data"), token));
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call,
                           Response<ResponseBody> response) {
        Log.v("Upload", "success");
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e("Upload error:", t.getMessage());
    }
});

}

person Linkang Ma    schedule 12.04.2016