Android — Как загрузить несколько изображений в одном запросе, используя Retrofit 2 и PHP в качестве серверной части?

Я делаю приложение, в котором пользователь может выбрать несколько изображений и загрузить их на сервер.
Я использую PHP в качестве бэкэнда и retrofit2

Я перепробовал все ответы на stackoverflow, но все еще не решил его.

@Multipart
@POST("URL/uploadImages.php")
Call<Response> uploaImages(
@Part List< MultipartBody.Part> 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();
}
});

}

вот мой php код

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
}
}
}

}

Решение:

Я понял проблему .. Я должен изменить имя MultipartBodt.Part от
"file" в "file[]"и принять их в $_FILES['file'] … так же, как вы делаете с традиционной формой … потому что я отправляю содержимое в виде данных формы
так что измени мой preparFfile() метод.

2

Решение

после поиска и расспросов, вот полное, проверенное и автономное решение.

1. Создать сервисный интерфейс.

public interface FileUploadService {

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

и ответ.java

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

}


2 — метод uploadImages

Я передаю список URI из onActivityResult() метод, то я получаю фактический путь к файлу с помощью FileUtiles «ссылка на класс закомментирована»

 //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());

}
});}

и вспомогательный метод, использованный выше

@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-мой php код 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);
?>
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]