Retrofit: Issue when uploading an image using Retrofit 2.0.1

Created on 4 Aug 2016  Â·  8Comments  Â·  Source: square/retrofit

Hello,

I am trying to upload an image to our project's server using Retrofit 2 but there seem to be an issue when sending the file.

The image is picked through an image picking activity and seems to work since the file (image) can be displayed using Picasso.

I tested it on Genymotion (5.0.0) and on my personal phone (5.0.2)

Retrofit succeeds however the server doesn't seem to get the file. Here are the server side log and code (written in Go).

screen_shot_2016-07-27_at_6 31 20_pm

func (c *gin.Context) {
   file, header , err := c.Request.FormFile("profileImage")
   // err = http: no such file
}

We are working on several platforms (IOS and WinPhone) and they manage to do that upload, therefore it's not a server side issue.

Here is the client side part :

Service :

@Multipart
@PATCH("/user/profileImage")
Call<ResponseBody> modifyUserImage(@Part("profileImage") RequestBody profileImage, @Part("userID") RequestBody userID);

Following code chunks are part of the same Fragment class

Opening image picking activity :

Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
getIntent.setType("image/*");

Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/*");

Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{pickIntent});

startActivityForResult(chooserIntent, 1);

On Activity Result:

    @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == Activity.RESULT_OK && requestCode == 1) {
        // process the result
        Uri selectedImage = data.getData();
        String wholeID = DocumentsContract.getDocumentId(selectedImage);
        String id = wholeID.split(":")[1];
        String[] column = {MediaStore.Images.Media.DATA};
        String sel = MediaStore.Images.Media._ID + "=?";
        Cursor cursor = getActivity().getContentResolver().
                query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[]{id}, null);
        String filePath = "";
        int columnIndex = cursor.getColumnIndex(column[0]);
        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();

        file = new File(filePath);
        Picasso
                .with(getActivity().getApplicationContext())
                .load(file)
                .into(civ_userProfilePicture);
    }
}

Request :

Note that even the RequestBody created from the File object prints coherent information when I tested it (size, image type...)

Call<ResponseBody> call = ServiceSingelton.getmInstance().getService()
                        .modifyUserImage(RequestBody.create(MediaType.parse("image/*"), file),
                                         RequestBody.create(MediaType.parse("text/plain"), ServiceSingelton.getmInstance().getUserID()));

call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if (response.code() == 200) {
            Log.d("RETROFIT SUCCESS", "Pic should be sent");
        } else {
            Log.d("RETROFIT SUCCESS", "Error code received modifying user");
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.d("RETROFIT ERROR", t.getMessage());
    }
});

All 8 comments

I had the same problem too.

Also have this problem. I think reason is in header of multipart body.
My code:
Observable<Response<Void>> uploadImage(@Part("file")RequestBody photo);
Headers of Multipart:

Content-Disposition: form-data; name="file"
Content-Transfer-Encoding: binary

name is "file", not file.

I think this is bug of Retrofit library

@JakeWharton please set label to "bug"

Provide a failing test case and I will.

On Tue, Aug 23, 2016, 8:10 AM Viktor Sinelnikov [email protected]
wrote:

@JakeWharton https://github.com/JakeWharton please set label to "bug"

—
You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
https://github.com/square/retrofit/issues/1958#issuecomment-241711004,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEcM_chnERurE56h-SuVc8jg85S7cks5qiuNIgaJpZM4JdGUn
.

To post a part with filename, you should change @Part("profileImage") RequestBody profileImage to @Part RequestBody profileImage, and pass it MultipartBody.Part.createFormData(partName, filename, requestBody):

// Service
@Multipart
@PATCH("/user/profileImage")
Call<ResponseBody> modifyUserImage(@Part MultipartBody.Part profileImage, @Part("userID") RequestBody userID);

// Call
MultipartBody.Part imagePart = MultipartBody.Part.createFormData("profileImage", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
Call<ResponseBody> call = ServiceSingelton.getmInstance().getService()
                        .modifyUserImage(imagePart,
                                         RequestBody.create(MediaType.parse("text/plain"), ServiceSingelton.getmInstance().getUserID()));

@baoti The method you gave worked, thanks a lot.

I am also facing same problem. Please help me out

My Request:
File file = new File(getPath(cropUriImage));
RequestBody requestBody = RequestBody.create(MediaType.parse("/"),file);
MultipartBody.Part imageToUpload = MultipartBody.Part.createFormData("profile_image",file.getName(),requestBody);
Call call = apiServiceInterface.UploadProfilePicFeed(filePart);
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
FlashbackFeeds.this.onSuccess(response);
}

        @Override
        public void onFailure(Call<DefaultModel> call, Throwable t) {
            FlashbackFeeds.this.onFailure(t);
        }
    });

Service:

@Multipart
@POST(Constants.URL.UPDATE_PROFILE_PIC)
Call UploadProfilePicFeed(@Part MultipartBody.Part filePart);

Was this page helpful?
0 / 5 - 0 ratings