I am making an app in which user can select multiple images and upload them to the server. I am using PHP as a backend and retrofit2
I tried all answers on stackoverflow but still did not resolve it.
@Multipart
@POST("URL/uploadImages.php")
Call<Response> uploaImages(
@Part List< MultipartBody.Part> files );
code for sending files
Retrofit builder = new Retrofit.Builder().baseUrl(ROOT_URL).addConverterFactory(GsonConverterFactory.create()).build();
FileUploadService fileUploadService = builder.create(FileUploadService.class);
Call<Response> call = fileUploadService.uploadImages(list)
for (Uri fileUri : path) {
MultipartBody.Part fileBody = prepareFilePart("files", fileUri);
images.add(fileBody);
}
Call<Response> call=fileUploadService.uploadImages(images);
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, Response<Response> response) {
Log.e("MainActivity",response.body().toString());
progressDialog.show();
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
Log.e("MainActivity",t.getLocalizedMessage());
progressDialog.dismiss();
}
});
}
here is my php code.
if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST"){
// Loop $_FILES to exeicute all files
foreach ($_FILES['files']['name'] as $f => $name) {
if ($_FILES['files']['error'][$f] == 4) {
continue; // Skip file if any error found
}
if ($_FILES['files']['error'][$f] == 0) {
if ($_FILES['files']['size'][$f] > $max_file_size) {
$message[] = "$name is too large!.";
continue; // Skip large files
}
elseif( ! in_array(pathinfo($name, PATHINFO_EXTENSION), $valid_formats) ){
$message[] = "$name is not a valid format";
continue; // Skip invalid file formats
}
else{ // No error found! Move uploaded files
if(move_uploaded_file($_FILES["files"]["tmp_name"][$f], $path.$name))
$count++; // Number of successfully uploaded file
}
}
}
}
Solution:
I figured out the problem ..I have to change the name of the MultipartBodt.Part
from
"file"
to "file[]"
.and receive them in $_FILES['file']
... the same as you do with traditional form ... because I am sending the content as a form-data
so modify my preparFfile()
method.
The solution for this problem is to pass a List or Array of MultipartBody. Part objects. Retrofit and OkHttp will then build an appropriate multipart request with all files. Java arrays or lists allow you to freely add files as required.
Tutorial ObjectiveCreate an HTML form to select multiple images and files. Display multiple images preview before sending to server. Implement necessary validation before uploading. Save files in the local directory and store the uploaded file path in the database.
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);
?>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With