Android: Retrofit 2 download multiple files?

Uploading a single image does not seem to pose a problem with modification 2.

However, I cannot figure out how to upload 2 images at a time.

if you follow the documentation: http://square.imtqy.com/retrofit/2.x/retrofit/retrofit2/http/PartMap.html

File file = new File(path, "theimage"); File file2 = new File(path2, "theimage"); RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file); RequestBody requestBody2 = RequestBody.create(MediaType.parse("image/png"), file2); Map<String, RequestBody> params = new HashMap<>(); params.put("image2", requestBody2 ); Call<ResponseBody> call = service.upload(requestBody, params); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Response<ResponseBody> response, Retrofit retrofit) { Log.v("Upload", "success"); } 

interface:

 public interface FileUploadService { @Multipart @POST("/upload") Call<ResponseBody> upload( //@Part("image_logo\"; filename=\"image.png\" ") RequestBody file, @Part("file") RequestBody file, @PartMap Map<String, RequestBody> params // @Part("description") String description ); 

this gives "Upload: success", but on the server side I get gibberish:

CONTENT_TYPE: multipart / form-data; border = 50fbfeb3-3abc-4f15-b130-cdcb7e3a0e4f

CONTENTS CONTENTS: Array ([file] => PNG IHDR L alotofbinarygibberish ....... snip [file2] => PNG IHDR L is more than binary gibberish ...

Can someone point me in the right direction?

single upload works, so the problem is not that I'm trying to upload 2 or more images.


if I change it to this:

 HashMap<String, RequestBody> partMap = new HashMap<String, RequestBody>(); partMap.put("file\"; filename=\"" + file.getName(), requestBody); partMap.put("file\"; filename=\"" + file2.getName(), requestBody); Call<ResponseBody> call = service.upload(partMap); 

 @Multipart @POST("/upload") Call<ResponseBody> upload( @PartMap() Map<String, RequestBody> partMap, 

I don't get any gibberish, but only the second image is uploaded ...!?


UPDATE

I tried this Retrofit (2.0 beta2) Downloading a multi-page file does not work , but I get an error message that @body cannot use with multipart: Java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding. (parameter # 1)

  for (String key : keys) { Bitmap bm = selectedImages.get(key); File f = new File(saveToInternalStorage(bm, key), key); if (f.exists()) { buildernew.addFormDataPart(key, key + ".png", RequestBody.create(MEDIA_TYPE, f)); } } RequestBody requestBody = buildernew.build(); 

-

 Call<ResponseBody> upload( @Body RequestBody requestBody 
+8
upload retrofit2 multiple-files
source share
3 answers

It works:

  final MediaType MEDIA_TYPE=MediaType.parse("image/png"); HashMap<String,RequestBody> map=new HashMap<>(selectedImages.size()); RequestBody file=null; File f=null; Set<String> keys = selectedImages.keySet(); for (String key : keys) { try { Bitmap bitmap = selectedImages.get(key); f = new File(saveToInternalStorage(bitmap, key), key); FileOutputStream fos = new FileOutputStream(f); if(bitmap!=null){ bitmap.compress(Bitmap.CompressFormat.PNG, 0 , fos); fos.flush(); fos.close(); } } catch (Exception e) { e.printStackTrace(); return; } file=RequestBody.create(MEDIA_TYPE, f); map.put(""+key+"\"; filename=\""+key+".jpg",file); Log.i("##MYLOG###", "### MAP PUT:" + key + " filename:"+key+".jpg file:" + file.toString() +" type:"+ file.contentType() ); file=null; f = null; } 

-

 Call<ResponseBody> upload( @PartMap() Map<String,RequestBody> mapFileAndName //for sending multiple images 

-

Beware: when debugging this with httpClient.interceptors (), I saw only one download, but when checking the very endpoint, to see what it actually received, the DID receives several downloads!

+6
source share

I may be late, but my answer may help future visitors.

I ask the user to select several images as follows:

 int PICK_IMAGE_MULTIPLE = 1; Intent intent = new Intent(); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE); 

Then in onActivityResult() I do this:

 ArrayList<String> filePaths; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_MULTIPLE) { if (data != null) { filePaths=new ArrayList<>(); // If data.getData() == null means multiple images selected, else single image selected. if (data.getData() == null) { ClipData clipData = data.getClipData(); if (clipData != null) { for (int i = 0; i < clipData.getItemCount(); i++) { ClipData.Item item = clipData.getItemAt(i); Uri uri = item.getUri(); filePaths.add(FileUtils.getPath(Activity.this, uri)); } } } else { filePaths.add(FileUtils.getPath(Activity.this,data.getData())); } sendToServer(); } } } 

You can get the FileUtils class from this Github link

My sendToServer() method looks like this:

 private void sendToServer() { if(filePaths!=null) { ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); MediaType MEDIA_TYPE_IMG = MediaType.parse("image/jpeg"); MultipartBody.Builder builder=new MultipartBody.Builder(); builder.setType(MultipartBody.FORM); RequestBody requestBody; try { for (int i = 0; i < filePaths.size(); i++) { File file = new File(filePaths.get(i)); requestBody=RequestBody.create(MEDIA_TYPE_IMG,file); builder.addFormDataPart("photo"+i,file.getName(),requestBody); } RequestBody finalRequestBody=builder.build(); Call<YourResponse> call=apiService.addEvent(finalRequestBody); call.enqueue(new Callback<YourResponse>() { @Override public void onResponse(Call<YourResponse> call, Response<YourResponse> response) { // process response } @Override public void onFailure(Call<YourResponse> call, Throwable t) { t.printStackTrace(); t.getCause(); } }); }catch (Exception e){ e.printStackTrace(); } } } 

Finally, my Retrofit endpoint is as follows:

 @POST("event/add") Call<YourResponse> addEvent(@Body RequestBody body); 

Note that YourResponse may be your custom model class to handle the response, or you can also use the raw Response class, which you do not want to make your model class.

We hope this helps new visitors.

+1
source share

try it

For API:

 //Multiple Images @Multipart @POST(HttpConstants.FILEMULTIPLEUPLOAD) Call<Result>uploadMultipleImage(@Part MultipartBody.Part files1,@Part MultipartBody.Part files2, @Query("total_images") int total, @Query("stdID") int stdID); 

Client

  public class RaytaServiceClass { public RaytaServiceClass() { } private static Retrofit getRetroClient(){ Gson gson = new GsonBuilder() .setLenient() .create(); return new Retrofit.Builder() .baseUrl(HttpConstants.baseUrl) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); } public static RaytaApi getApiService(){ return getRetroClient().create(RaytaApi.class); } } 

Call

  RaytaApi service= RaytaServiceClass.getApiService(); File file1 = new File(selectedPath1); File file2 = new File(selectedPath2); RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file1); RequestBody requestFile2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2); MultipartBody.Part body = MultipartBody.Part.createFormData("uploaded_file", file1.getName(), requestFile); MultipartBody.Part body2 = MultipartBody.Part.createFormData("uploaded_file", file2.getName(), requestFile2); Call<Result> resultCall=service.uploadMultipleImage(body,body2,2,1); Log.v("@@@@WWE","REquest "+resultCall.toString()); Log.v("@@@WWE","Retrofit Request Method = "+resultCall.request().method()); Log.v("@@@WWE","Retrofit Request Body = "+resultCall.request().body()); Log.v("@@@WWE","Retrofit Request Url = "+resultCall.request().url()); final Result[] result = {new Result()}; resultCall.enqueue(new Callback<Result>() { @Override public void onResponse(Call<Result> call, Response<Result> response) { progressDialog.dismiss(); Log.v("@@@WWE","Respnse"); result[0] =response.body(); Log.v("@@@WWE","Response Result "+result[0].getResult()); if(response.isSuccessful()){ Toast.makeText(UploadMultipleImageActivity.this,"Sucess",Toast.LENGTH_SHORT).show(); Toast.makeText(UploadMultipleImageActivity.this,"Press Refresh Button",Toast.LENGTH_LONG).show(); supportFinishAfterTransition(); } } @Override public void onFailure(Call<Result> call, Throwable t) { progressDialog.dismiss(); Log.v("@@@WWE","Failure "); Log.v("@@@WWE","MEssage "+t.getMessage()); } }); 
0
source share

All Articles