Retrofit Uploading Multiple Images to a Single Key

Retrofit Uploading multiple images to a single key

We can use MultipartBody.Part array to upload an array of images to a single key.
Here is the solution

WebServicesAPI

@Multipart
@POST(WebServices.UPLOAD_SURVEY)
Call<UploadSurveyResponseModel> uploadSurvey(@Part MultipartBody.Part[] surveyImage,
@Part MultipartBody.Part propertyImage,
@Part("DRA") RequestBody dra);

Here is the method for uploading the files.

private void requestUploadSurvey () {
File propertyImageFile = new File(surveyModel.getPropertyImagePath());
RequestBody propertyImage = RequestBody.create(MediaType.parse("image/*"),
propertyImageFile);
MultipartBody.Part propertyImagePart = MultipartBody.Part.createFormData("PropertyImage",
propertyImageFile.getName(),
propertyImage);

MultipartBody.Part[] surveyImagesParts = new MultipartBody.Part[surveyModel.getPicturesList()
.size()];

for (int index = 0; index <
surveyModel.getPicturesList()
.size(); index++) {
Log.d(TAG,
"requestUploadSurvey: survey image " +
index +
" " +
surveyModel.getPicturesList()
.get(index)
.getImagePath());
File file = new File(surveyModel.getPicturesList()
.get(index)
.getImagePath());
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"),
file);
surveyImagesParts[index] = MultipartBody.Part.createFormData("SurveyImage",
file.getName(),
surveyBody);
}

final WebServicesAPI webServicesAPI = RetrofitManager.getInstance()
.getRetrofit()
.create(WebServicesAPI.class);
Call<UploadSurveyResponseModel> surveyResponse = null;
if (surveyImagesParts != null) {
surveyResponse = webServicesAPI.uploadSurvey(surveyImagesParts,
propertyImagePart,
draBody);
}
surveyResponse.enqueue(this);
}

How To Upload Multiple Image to single key using retrofit in android

my key is multipleimage[] like this and it is working well in this

  VolleyMultipartRequest volleyMultipartRequest = new 

VolleyMultipartRequest(com.android.volley.Request.Method.POST, url,


new com.android.volley.Response.Listener<NetworkResponse>() {

@Override
public void onResponse(NetworkResponse response) {
try {
Log.e("respps", "onResponse: " + response);

Toast.makeText(PostFormActivity.this,"UploadSucessfully", Toast.LENGTH_SHORT).show();

} catch (Exception e) {
e.printStackTrace();
Log.e("respps", "onResponse:Exp " + e.getMessage());
Toast.makeText(PostFormActivity.this, "Upload Fail", Toast.LENGTH_SHORT).show();

}

}
},
new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {

Log.e("ERROR", error.toString());
Log.e("respps", "onResponse:Err " + error);

Toast.makeText(PostFormActivity.this, "Upload Fail Try After Some Time", Toast.LENGTH_SHORT).show();

}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("id", id);
params.put("id2", id2);
params.put("id3",id3);
params.put("id4", id4);

return params;
}

@Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
long imagename = System.currentTimeMillis();
params.put("banner", new DataPart(imagename + ".png", getFileDataFromDrawable(img)));

for (int i = 0; i < imagesEncodedList1.size(); i++) {
params.put("multipleimage" + "[" + i + "]", new DataPart(imagename + ".png", getFileDataFromDrawable(imagesEncodedList1.get(i))));
}
return params;
}
};
{
int socketTimeout = 60000;
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
volleyMultipartRequest.setRetryPolicy(policy);
RequestQueue requestQueue = Volley.newRequestQueue(PostFormActivity.this);
requestQueue.add(volleyMultipartRequest);

}

volley multipart request

    public class VolleyMultipartRequest extends Request<NetworkResponse> {
private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();

private Response.Listener<NetworkResponse> mListener;
private Response.ErrorListener mErrorListener;
private Map<String, String> mHeaders;

public VolleyMultipartRequest(int method, String url,
Response.Listener<NetworkResponse> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;

this.mErrorListener = errorListener;
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders != null) ? mHeaders : super.getHeaders();
}

@Override
public String getBodyContentType() {
return "multipart/form-data;boundary=" + boundary;
}

@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);

try {
// populate text payload
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
textParse(dos, params, getParamsEncoding());
}

// populate data byte payload
Map<String, DataPart> data = getByteData();
if (data != null && data.size() > 0) {
dataParse(dos, data);
}

// close multipart form data after text and file data
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* Custom method handle data payload.
*
* @return Map data part label with data byte
* @throws AuthFailureError
*/
protected Map<String, DataPart> getByteData() throws AuthFailureError {
return null;
}

@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(
response,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}

@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}

@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}

/**
* Parse string map into data output stream by key and value.
*
* @param dataOutputStream data output stream handle string parsing
* @param params string inputs collection
* @param encoding encode the inputs, default UTF-8
* @throws IOException
*/
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
}
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + encoding, uee);
}
}

/**
* Parse data into data output stream.
*
* @param dataOutputStream data output stream handle file attachment
* @param data loop through data
* @throws IOException
*/
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
for (Map.Entry<String, DataPart> entry : data.entrySet()) {
buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
}
}

/**
* Write string data into header and data output stream.
*
* @param dataOutputStream data output stream handle string parsing
* @param parameterName name of input
* @param parameterValue value of input
* @throws IOException
*/
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(parameterValue + lineEnd);
}

/**
* Write data file into header and data output stream.
*
* @param dataOutputStream data output stream handle data parsing
* @param dataFile data byte as DataPart from collection
* @param inputName name of data input
* @throws IOException
*/
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
}
dataOutputStream.writeBytes(lineEnd);

ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
int bytesAvailable = fileInputStream.available();

int maxBufferSize = 1024 * 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];

int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

dataOutputStream.writeBytes(lineEnd);
}

public class DataPart {
private String fileName;
private byte[] content;
private String type;

public DataPart() {
}

DataPart(String name) {
fileName = name;
// content = data;
}

public DataPart(String s, byte[] fileDataFromDrawable) {
fileName = s;
content=fileDataFromDrawable;
}

String getFileName() {
return fileName;
}

byte[] getContent() {
return content;
}

String getType() {
return type;
}

}
}

get file data from drawable

    public byte[] getFileDataFromDrawable(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new
ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 80,
byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}

and here my onActivityResult

      if (requestCode == 44 && resultCode == RESULT_OK && data != null && data.getData() != null) {
String[] filePathColumn = { MediaStore.Images.Media.DATA };
imagesEncodedList = new ArrayList<String>();
imagesEncodedList1 = new ArrayList<Bitmap>();
if(data.getClipData() != null) {
int count = data.getClipData().getItemCount();
for(int i = 0; i < count; i++) {
Uri imageUri = data.getClipData().getItemAt(i).getUri();


Cursor cursor = getContentResolver().query(data.getClipData().getItemAt(i).getUri(), filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageEncoded = cursor.getString(columnIndex);
imagesEncodedList.add(imageEncoded);

try {
Bitmap bitmap = MediaStore
.Images
.Media
.getBitmap(PostFormActivity.this.getContentResolver(), data.getClipData().getItemAt(i).getUri());
imagesEncodedList1.add(bitmap);
Log.d("TAG", "onActivityResult:trybitmap "+bitmap);
}
catch (Exception e){
e.printStackTrace();

}
cursor.close();
//do what do you want to do
}
}
}

Select Multiple Image from gallery

    private void selectMultipleImage() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(Intent.createChooser(intent, "Select
images"),44);
}

Sending multiple images using retrofit in a single key

file was not uploading because file was not Creating Properly
thanks to github i found a way to create a file Properly

GitHub link for creating file

Also Made a little bit of changes in my code according to this answer
link for stackoverflow answer

How to upload multiple images in android using retrofit

public interface UploadImages {  
@Multipart
@POST("upload_images")
Call<ResponseBody> uploadMultipleFiles(
@Part("text") RequestBody text,
@Part List<MultipartBody.Part> images);
}

OR

 @Multipart
@POST("upload_images")
Call<ResponseBody> uploadMultipleFiles(@Part("text") RequestBody text,
@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2,
@Part MultipartBody.Part file3);

How to upload Multiple images in one Request using Retrofit 2 and php as a back end?

after searching and asking around, here is a full, tested and self-contained solution.

1.create the service interface.

public interface FileUploadService {

@Multipart
@POST("YOUR_URL/image_uploader.php")
Call<Response> uploadImages( @Part List<MultipartBody.Part> images);
}

and the Response.java

public class Response{
private String error;
private String message;
//getters and setters

}


2- uploadImages method

I pass a list of URI from onActivityResult() method, then I get the actual file path with the help of FileUtiles "the link to the class is commented"

 //code to upload
//the path is returned from the gallery
void uploadImages(List<Uri> paths) {
List<MultipartBody.Part> list = new ArrayList<>();
int i = 0;
for (Uri uri : paths) {
String fileName = FileUtils.getFile(this, uri).getName();
//very important files[]
MultipartBody.Part imageRequest = prepareFilePart("file[]", uri);
list.add(imageRequest);
}

Retrofit builder = new Retrofit.Builder().baseUrl(ROOT_URL).addConverterFactory(GsonConverterFactory.create()).build();
FileUploadService fileUploadService = builder.create(FileUploadService.class);
Call<Response> call = fileUploadService.uploadImages(list);
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, Response<Response> response) {
Log.e("main", "the message is ----> " + response.body().getMessage());
Log.e("main", "the error is ----> " + response.body().getError());

}

@Override
public void onFailure(Call<Response> call, Throwable throwable) {
Log.e("main", "on error is called and the error is ----> " + throwable.getMessage());

}
});

}

and the helper method used above

@NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
// use the FileUtils to get the actual file by uri
File file = FileUtils.getFile(this, fileUri);
//compress the image using Compressor lib
Timber.d("size of image before compression --> " + file.getTotalSpace());
compressedImageFile = new Compressor(this).compressToFile(file);
Timber.d("size of image after compression --> " + compressedImageFile.getTotalSpace());
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(
MediaType.parse(getContentResolver().getType(fileUri)),
compressedImageFile);

// MultipartBody.Part is used to send also the actual file name
return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}

3-My php code image_uploader.php:

    <?php
$file_path = "upload/";
$full_path="http://bishoy.esy.es/retrofit/".$file_path;
$img = $_FILES['file'];
$response['message'] = "names : ";
if(!empty($img)){

for($i=0;$i<count($_FILES['file']['tmp_name']);$i++){

$response['error'] = false;
$response['message'] = "number of files recieved is = ".count($_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'][$i],"upload/".$_FILES['file']['name'][$i])){
$response['error'] = false;
$response['message'] = $response['message']. "moved sucessfully :: ";

}else{
$response['error'] = true;
$response['message'] = $response['message'] ."cant move :::" .$file_path ;

}
}
}
else{
$response['error'] = true;
$response['message'] = "no files recieved !";
}

echo json_encode($response);
?>

How to send multiple images to server using retrofit 2.3.0 in android?

Instead of using @Part try @Field

@Multipart
@POST("/api/mbrphotos/prfImgIU/{memberId}/{actionType}")
Call<JsonObject> postImage(@Part("memberId") RequestBody memberId,
@Part("actionType") RequestBody actionType,
@Part MultipartBody.Part[] multipartTypedOutput);

and in your Activity use this method to send the post

public void sendPost(String memberId, String actionType) {
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Please wait...");
dialog.setCancelable(false);
dialog.show();

MultipartBody.Part[] multipartTypedOutput = new MultipartBody.Part[imageModelArrayList.size()];

for (int index = 0; index < imageModelArrayList.size(); index++) {
Log.d("Upload request", "requestUploadSurvey: survey image " + index + " " + imageModelArrayList.get(index).path);
File file2 = new File(imageModelArrayList.get(index).path);
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"), file2);
multipartTypedOutput[index] = MultipartBody.Part.createFormData("imageFiles[]", file2.getPath(), surveyBody);
}

RequestBody memberId1 = RequestBody.create(MediaType.parse("text/plain"), memberId);
RequestBody actionType1 = RequestBody.create(MediaType.parse("text/plain"), actionType);

apiService.postImage(memberId1, actionType1, multipartTypedOutput).enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
Log.d("fb_regist_response", "--->" + "" + response);
dialog.dismiss();
}

@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.d("onFail_fb_regist_res", t.getMessage());
dialog.dismiss();
}
});

}


Related Topics



Leave a reply



Submit