【问题标题】:How to upload Multiple images in one Request using Retrofit 2 and php as a back end?如何使用 Retrofit 2 和 php 作为后端在一个请求中上传多个图像?
【发布时间】:2017-08-19 10:53:57
【问题描述】:

我正在制作一个应用程序,用户可以在其中选择多个图像并将它们上传到服务器。 我使用 PHP 作为后端和改造 2

我在 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() 方法。

【问题讨论】:

标签: php android file-upload retrofit2 multipart


【解决方案1】:

经过搜索和询问,这里有一个完整的、经过测试的、独立的解决方案。

1.创建服务接口。

public interface FileUploadService {

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

和 Response.java

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

}


2-uploadImages方法

我从onActivityResult() 方法传递了一个URI 列表,然后我在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);
?>

【讨论】:

  • 您的代码工作正常,但我需要在上传之前压缩图像...有什么想法吗?
  • 很高兴它有帮助。我通常使用图像压缩库。它易于使用且高效。
  • 你能解释一下吗?具体压缩到哪里以及压缩后的最终文件类型是什么
  • 查看更新后的答案,特别是 prepareFilePart() 方法
  • 非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多