Reputation: 277
Uploading a single image seems to be no problem with retrofit 2.
However, i cant figure out how to upload 2 images at the same time.
if followed the documentation: http://square.github.io/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 a 'Upload: success' but on the server side i get gibberish:
CONTENT_TYPE: multipart/form-data; boundary=50fbfeb3-3abc-4f15-b130-cdcb7e3a0e4f
CONTENT POST:Array ( [file] => �PNG IHDR L alotofbinarygibberish.... ... snip [file2] => �PNG IHDR L more binary gibberish...
can anyone point me in the right direction?
single upload does work so thats not the problem, 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 get no gibberish but only the second image is uploaded... !?
i tried this Retrofit(2.0 beta2) Multipart file upload doesn't work solution but get an error that @body can not me used 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
Upvotes: 10
Views: 8596
Reputation: 654
Try This
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);
}
}
The 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());
}
});
Upvotes: 1
Reputation: 1062
I might be late but my answer might help future visitors
I am asking user to select multiple images like this:
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 am doing 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 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 looks like this:
@POST("event/add")
Call<YourResponse> addEvent(@Body RequestBody body);
Note that YourResponse
can be your custom model class for handling response, or you can also use raw Response
class in you don't want to make your model class.
Hope this helps new visitors.
Upvotes: 2
Reputation: 277
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: while debugging this with the httpClient.interceptors() i saw only a single upload but when checking the endpoint itself to see what it actually got, it DID get the multiple uploads!
Upvotes: 7