Jolson Da Costa
Jolson Da Costa

Reputation: 1105

Retrofit v2.0.0-beta2 how to upload file using RequestBody

I am trying to post images to the server. Here are my php variable names on the server side provided to me by scriptor:

$value1 = $_POST["value1"]; // string value
$value2 = $_POST["value2"]; // string value

$img_1 = $_FILES["fileToUpload1"]["name"]; // image file
$img_2 = $_FILES["fileToUpload2"]["name"]; // image file

and here is my code for posting the values -

RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), path.toString());
RequestBody fileBody1 = RequestBody.create(MediaType.parse("image/png"), path.toString());

Call<uploadResponseModel> call = adapter.uploadValues("test1","test2",fileBody1,fileBody);

call.enqueue(new Callback<uploadResponseModel>() {
    @Override
    public void onResponse(Response<uploadResponseModel> response, Retrofit retrofit) {
         Log.i("TAG", "retro onResponse :" + response.body().getResponse().getStatus());
    }

    @Override
    public void onFailure(Throwable t) {
        Log.i("TAG", "retro onFailure :" + t.getCause());
    }
});

adapter class:

public interface RetrofitAdapter {
 @Multipart
 @POST("/TestApp/img_upload.php")
 Call<uploadResponseModel> uploadValues(@Part("value1")String  value1,@Part("value2")String  value2,@Part("fileToUpload1") RequestBody file1,@Part("fileToUpload2") RequestBody file2);
}

Both string values are getting posted on the server, but not the images. Please correct me if i am wrong anywhere in posting image files. I am new to retrofit.

Upvotes: 2

Views: 1541

Answers (6)

Rohit TP
Rohit TP

Reputation: 76

As per your question, the variable that your server expects as the two images(files) are fileToUpload1 and fileToUpload2. The reason why the images are'nt getting uploaded are because of the syntax you have specified in your RetrofitAdapter.

You will have to change your RetrofitAdapter to:

public interface RetrofitAdapter {
 @Multipart
 @POST("/TestApp/img_upload.php")
 Call<uploadResponseModel> uploadValues(@Part("value1")String  value1,@Part("value2")String  value2,@Part("fileToUpload1\"; filename=\"image\" ") RequestBody file1,@Part("fileToUpload2\"; filename=\"image\" ") RequestBody file2);
}

@Part("fileToUpload1\"; filename=\"image\" ") RequestBody file1

The server expects the file with the variable name fileToUpload1 and fileToUpload2 which has to be posted along with a file name in the above format. You could refer the solution here as well click here

Do this and you are good to go :)

Upvotes: 6

rejanipillai
rejanipillai

Reputation: 1

There are some issues with multipart file upload with retrofit @Multipart tag.

Solved the issue using the @POST tag, with custom multipart builder in request body.

@POST ("userwebservices/app_upload_pic")
Call<APIRespone> uploadUserImages ( @Body RequestBody file );

Code for multipart upload by passing image file path getting from android app.

 File file = new File(filePath);

 MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");
 RequestBody requestBody = new MultipartBuilder()
         .type(MultipartBuilder.FORM)
         .addPart(
                 Headers.of("Content-Disposition", "form-data;name=\"uploaded_file\";filename=\"" + filePath + "\""),
                 RequestBody.create(MEDIA_TYPE_IMAGE, file))
         .build();

Here uploaded_file is the checking string in the PHP script.

Upvotes: -1

kphil
kphil

Reputation: 1006

This is my service method for multipart file upload:

@Multipart
@POST("http://....")
Call<UploadResponse> uploadPicture(@PartMap Map<String,RequestBody>  pic1, @PartMap Map<String, RequestBody> pic2);

And how to call it:

  public void uploadPicture(File pic1, File pic2) {
      Map<String, RequestBody> pic1Map = new HashMap<>();
      Map<String, RequestBody> pic2Map = new HashMap<>();
      RequestBody rb1 = RequestBody.create(MediaType.parse("image/*"), pic1);
      RequestBody rb2 = RequestBody.create(MediaType.parse("image/*"), pic2);
      pic1Map.put("file\"; filename=\"" + pic1.getName(), rb1);
      pic2Map.put("file\"; filename=\"" + pic2.getName(), rb2);

      Call<UploadResponse> call = apiClient.getAPIService().uploadPicture(pic1Map, pic2Map); 
      call.enqueue...
  }

Some backends require the filename header parameter, that's why i use @PartMap this way. OkHttp's multipart builder does not set it.

Upvotes: 2

Niko Adrianus Yuwono
Niko Adrianus Yuwono

Reputation: 11112

I think the method to sent normal string and file is different.

you should use

@Part("file\"; filename=\"fileToUpload1.png\"") RequestBody file1

instead of

@Part("fileToUpload1") RequestBody file1

or if you want to be specific

@Part("image\"; filename=\"fileToUpload1.png\"") RequestBody file1

Upvotes: 0

iagreen
iagreen

Reputation: 32016

You are calling the wrong create method of RequestBody. You are passing a string, which uses the string as the content. You need to be passing a File. It is not clear what type your path variable is. If it is already a File, use it. Otherwise, create a file and pass that to create --

File image = new File(path.toString());
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), image);

do the same for fileBody1.

Upvotes: 0

ArtKorchagin
ArtKorchagin

Reputation: 4853

Instead of RequestBody just use RequestBody. Fix method uploadValues in Retrofit interface:

           public interface RetrofitAdapter {
           @Multipart
           @POST("/TestApp/img_upload.php")
           Call<uploadResponseModel> uploadValues(@Part("value1")String  value1,@Part("value2")String  value2,@Part("fileToUpload1") TypedFile file1,@Part("fileToUpload2") TypedFile file2);
           }

And fix your request service:

           TypedFile file1 = new TypedFile("application/octet-stream", new File(path1));
           TypedFile file2 = new TypedFile("application/octet-stream", new File(path2));
           Call<uploadResponseModel> call = adapter.uploadValues("test1","test2",file1,file2);

           call.enqueue(new Callback<uploadResponseModel>() {
               @Override
               public void onResponse(Response<uploadResponseModel> response, Retrofit retrofit) {
                   Log.i("TAG", "retro onResponse :" + response.body().getResponse().getStatus());

               }

               @Override
               public void onFailure(Throwable t) {
                   Log.i("TAG", "retro onFailure :" + t.getCause());

               }
           });

Upvotes: 0

Related Questions