【问题标题】:Retrofit Uploading multiple images to a single key改造将多个图像上传到单个密钥
【发布时间】:2017-02-13 11:14:15
【问题描述】:

我正在使用 Retrofit 将图像上传到我的服务器。在这里,我需要为一个键上传多个图像。我已经尝试过使用 Postman 网络客户端,它运行良好。这是截图。

这里是请求的键值对。
SurveyImage : [file1,file2,file3];
属性图像:文件
DRA:jsonBody

我尝试对 Retrofit 做同样的事情。但图像没有上传到服务器。这是我的代码。
WebServicesAPI.java

public interface WebServicesAPI {
    @Multipart
    @POST(WebServices.UPLOAD_SURVEY)
    Call<UploadSurveyResponseModel> uploadSurvey(@Part MultipartBody.Part surveyImage, @Part MultipartBody.Part propertyImage, @Part("DRA") RequestBody dra);
}

这是上传文件的方法。

 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);
        JSONObject requestBody = getRequestBody();
        RequestBody draBody = null;
        try {
            draBody = RequestBody.create(MediaType.parse("text/plain"), requestBody.toString(1));
            Log.d(TAG, "requestUploadSurvey: RequestBody : " + requestBody.toString(1));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        MultipartBody surveyImage = null;

            for (SurveyModel.PictureModel model : surveyModel.getPicturesList()) {
                File file = new File(model.getImagePath());
                builder.addFormDataPart("SurveyImage", file.getName(),
                        RequestBody.create(MediaType.parse("image/*"), file));
            }
            surveyImage = builder.build();

        final WebServicesAPI webServicesAPI = RetrofitManager.getInstance().getRetrofit().create(WebServicesAPI.class);
        Call<UploadSurveyResponseModel> surveyResponse = null;

            surveyResponse = webServicesAPI.uploadSurvey(MultipartBody.Part.createFormData("SurveyImage", "SurveyImage", surveyImage), propertyImagePart, draBody);

        surveyResponse.enqueue(this);

        Log.d(TAG, "requestUploadSurvey: sent the request");
    }

请帮我解决这个问题。

【问题讨论】:

    标签: android multipartform-data retrofit2 okhttp


    【解决方案1】:

    我们可以使用MultipartBody.Part 数组将一组图像上传到单个键。 这是解决方案
    WebServicesAPI

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

    这是上传文件的方法。

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

    【讨论】:

    • 我无法使用MultipartBody.Part [] 上传多张图片,它总是只上传数组中的最后一张图片。你能说清楚你在哪里使用图像数组的键吗?提前致谢。
    • 确保只创建一个对数组的引用,并将所有图像添加到该数组中。查看 WebServicesAPI 中的 uploadSurvey 方法以供参考。
    • 总是出现以下错误@Part 注释必须提供名称或使用 MultipartBody.Part 参数类型。
    • 只上传first图片MultipartBody.Part[] surveyImagesParts = new MultipartBody.Part[MySharedPreferences.all_sharedprefrenceaddimage.size()]; for (int i=0;i&lt;MySharedPreferences.all_sharedprefrenceaddimage.size();i++){ File file = new File(MySharedPreferences.all_sharedprefrenceaddimage.get(i)); RequestBody surveyBody = RequestBody.create(MediaType.parse("image"), file); surveyImagesParts[i] = MultipartBody.Part.createFormData("photos[]", file.getName(), surveyBody); }
    • createFormData第一个参数字符串末尾加[]解决了surveyImagesParts.add(MultipartBody.Part.createFormData("images[]", file.getName(), surveyBody));只上传1张图片的问题
    【解决方案2】:

    我在接受的答案上浪费了很多时间。但这对我来说不起作用。 所以经过大量搜索,我找到了这个。就我而言,它 100% 有效。

    private void uploadMultiFile() {
    
    
        ArrayList<String> filePaths = new ArrayList<>();
        filePaths.add("storage/emulated/0/DCIM/Camera/IMG_20170802_111432.jpg");
        filePaths.add("storage/emulated/0/Pictures/WeLoveChat/587c4178e4b0060e66732576_294204376.jpg");
        filePaths.add("storage/emulated/0/Pictures/WeLoveChat/594a2ea4e4b0d6df9153028d_265511791.jpg");
    
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
    
        builder.addFormDataPart("user_name", "Robert");
        builder.addFormDataPart("email", "mobile.apps.pro.vn@gmail.com");
    
        // Map is used to multipart the file using okhttp3.RequestBody
        // Multiple Images
        for (int i = 0; i < filePaths.size(); i++) {
            File file = new File(filePaths.get(i));
            builder.addFormDataPart("file[]", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
        }
    
    
        MultipartBody requestBody = builder.build();
        Call<ResponseBody> call = uploadService.uploadMultiFile(requestBody);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
    
                Toast.makeText(MainActivity.this, "Success " + response.message(), Toast.LENGTH_LONG).show();
    
    
    
    
            }
    
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
    
                Log.d(TAG, "Error " + t.getMessage());
            }
        });
    
    
    }
    

    这是界面

    @POST("/upload_multi_files/MultiPartUpload.php")
    Call<ResponseBody> uploadMultiFile(@Body RequestBody file);
    

    【讨论】:

    • @Body 参数不能与表单或多部分编码一起使用。收到此错误。
    • 再试一次.. 会好的... @Ali_Waris 我有时也会遇到这个错误,但后来就好了。
    • @ImranSamed 这是一个例外,使我的应用程序崩溃。我需要避免它。
    • @Ali_Waris 您是否成功避免了此错误?我遇到了同样的错误。 – Taynã Bonaldo 7 秒前编辑
    • @Ali_Waris 我通过将“requestBody.parts()”传递给方法而不是 requestBody 对象解决了这个错误。然后在 Retrofit API 界面中,我将“@Body RequestBody 文件”更改为“@Part List 文件”。我希望它有所帮助。
    【解决方案3】:

    我尝试过的最佳解决方案

    API接口:

    @Multipart
        @POST("person/img")
        Call<ResponseBody> upImageMany(@Part List<MultipartBody.Part> file);
    

    活动:

    List<MultipartBody.Part> parts = new ArrayList<>();
    
    for (int i=0; i < upFileList.size(); i++){
        parts.add(prepareFilePart("my_file["+i+"]", upFileList.get(i)));
    }
    
    private MultipartBody.Part prepareFilePart(String partName, Uri fileUri){
    
            File file = new File(getPath(fileUri));
    
            RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
    
            return MultipartBody.Part.createFormData(partName, file.getName(),requestBody);
        }
    

    【讨论】:

    • @PriyankaSingh 有什么可以帮你的
    【解决方案4】:

    对于单个键,您可以使用,

      @POST("upload/images")
      Observable<YourBaseResponse>
      uploadMultipleImages(@Body RequestBody imagesBody);
    

    您可以按如下方式创建 RequestBody,

     public static MultipartBody buildMultipartForMultipleImages(Context context, List<MediaPreviewModel> allAddMediaImages) {
    
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
    
            for (int index = 0; index < allAddMediaImages.size(); index++) {
                
                    builder.addFormDataPart("images", "image" + index, getRequestBodyForImages(context, allAddMediaImages.get(index).getUri()));
                
            }
            return builder.build();
    
        }
    

    其中 MediaPreviewModel 是包含图像详细信息(URI、文件名、扩展名、大小等)的 POJO。

    将请求正文创建为

      public static RequestBody getRequestBodyForImages(Context context, Uri uri) {
            File file = null;
            try {
                file = getFile(context, uri);
            } catch (IOException e) {
                e.printStackTrace();
            }
            File file1 = CompressFile.getCompressedImageFile(file, context);
            RequestBody imageReqBody;
            if (file1 != null) {
                imageReqBody = RequestBody.create(file1, MediaType.parse("image/jpg"));
            } else {
                assert file != null;
                imageReqBody = RequestBody.create(file, MediaType.parse("image/jpg"));
            }
            return imageReqBody;
        }
    

    【讨论】:

      猜你喜欢
      • 2020-07-29
      • 2020-11-20
      • 2017-09-11
      • 1970-01-01
      • 1970-01-01
      • 2019-12-19
      • 2021-07-03
      • 1970-01-01
      • 2021-04-07
      相关资源
      最近更新 更多