“Retrofit”如何在一个多部分请求中附加多个图像

24

有没有办法在一个多部分请求中附加多个图像?这些图像根据用户选择的数量是动态的。

以下代码仅适用于单个图像:

接口:

@Multipart
@POST("/post")
void createPostWithAttachments( @Part("f[]") TypedFile image,@PartMap Map<String, String> params,Callback<String> response);

实现:

TypedFile file = new TypedFile("image/jpg", new File(gallery.sdcardPath));

Map<String,String> params = new HashMap<String,String>();
params.put("key","value");

ServicesAdapter.getAuthorizeService().createPostWithAttachments(file,params, new Callback<String>() {
        @Override
        public void success(String s, Response response) {
            DBLogin.updateCookie(response);
            new_post_text.setText("");
            try {
                JSONObject json_response = new JSONObject(s);
                Toast.makeText(getApplicationContext(), json_response.getString("message"), Toast.LENGTH_LONG).show();
                if (json_response.getString("status").equals("success")) {
                    JSONObject dataObj = json_response.getJSONObject("data");
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Log.d(TAG, "Request failed");
                }
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
            }
        }

        @Override
        public void failure(RetrofitError retrofitError) {
            Toast.makeText(getApplicationContext(), retrofitError.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
2个回答

32

在查看了Retrofit提供的文档后,我能够用自己的解决方案完成它,也许不是很好,但仍然成功地使其工作。

这是参考资料 MultipartTypedOutput

实际上与上面的先前代码非常相似,只需做出一些小修改即可。

接口

@POST("/post")
void createPostWithAttachments( @Body MultipartTypedOutput attachments,Callback<String> response);

实现

    MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
    multipartTypedOutput.addPart("c", new TypedString(text));
    multipartTypedOutput.addPart("_t", new TypedString("user"));
    multipartTypedOutput.addPart("_r", new TypedString(userData.user.id));

    //loop through object to get the path of the images that has picked by user
    for(int i=0;i<attachments.size();i++){
        CustomGallery gallery = attachments.get(i);
        multipartTypedOutput.addPart("f[]",new TypedFile("image/jpg",new File(gallery.sdcardPath)));
    }

    ServicesAdapter.getAuthorizeService().createPostWithAttachments(multipartTypedOutput, new Callback<String>() {
        @Override
        public void success(String s, Response response) {
            DBLogin.updateCookie(response);
            new_post_text.setText("");
            try {
                JSONObject json_response = new JSONObject(s);
                Toast.makeText(getApplicationContext(), json_response.getString("message"), Toast.LENGTH_LONG).show();
                if (json_response.getString("status").equals("success")) {
                    JSONObject dataObj = json_response.getJSONObject("data");
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Log.d(TAG, "Request failed");
                }
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
            }
        }

        @Override
        public void failure(RetrofitError retrofitError) {
            Toast.makeText(getApplicationContext(), retrofitError.getMessage(), Toast.LENGTH_LONG).show();
        }
    });

也许这个解决方案并不是那么好,但希望它能帮助其他人。
如果有更好的解决方案,请提出建议,谢谢 :D

更新

在Retrofit 2.0.0-beta1中,MultipartTypedOutput不再存在。
现在想上传多张图片的人可以使用@PartMap,参考链接 javadoc

这对我非常有用,因为我需要具有相同名称但不同值的零件。类似于数组,但名称不能带有“[]”和新零件。 - Ray Hunter
1
运行得非常好。谢谢!注意:在使用Body和POST时,请不要忘记删除@Multipart注释! - voghDev
在我的情况下,MultipartTypedOutput 比 part 运行得更慢,我不知道为什么会发生这种情况,请问您能告诉我吗? - aman verma
哥们,能不能告诉我你是怎么挑选图片的?我不太理解循环部分,这个应用程序最后一个特性将要让我崩溃了。 - H4F
有没有关于Retrofit 2的解决方案,因为它现在无法工作? - Jemshit Iskenderov
@JemshitIskenderov 请查看重复问题 https://dev59.com/qmEh5IYBdhLWcg3wNxPM#32275127 - Boris Treukhov

4
//We need to create the Typed file array as follow and add the images path in the arrays list.



    private ArrayList<TypedFile> images;

        private void postService(final Context context) {
            Utils.progressDialog(context);
            MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
            multipartTypedOutput.addPart("user_id",new TypedString(strUserId));
            multipartTypedOutput.addPart("title", new TypedString(strJobtitle));
            multipartTypedOutput.addPart("description", new TypedString(
                    strJobdescription));
            multipartTypedOutput.addPart("experience", new TypedString(
                    strUserExperience));
            multipartTypedOutput.addPart("category_id", new TypedString(
                    strPostCategory));
            multipartTypedOutput.addPart("city_id", new TypedString(strCityCode));
            multipartTypedOutput.addPart("country_id", new TypedString(
                    strCountryCode));       
    multipartTypedOutput.addPart("profile_doc",new TypedFile("multipart/form-data", postCurriculamFile));
    for (int i = 0; i < images.size(); i++) {
                multipartTypedOutput.addPart("image[]", images.get(i));
    }       

    PostServiceClient.getInstance().postServiceData(multipartTypedOutput,
                    new Callback<RegistrationResponsModel>() {
                @Override
                public void failure(RetrofitError retrofitError) {
                    Logger.logMessage("fail" + retrofitError);
                    Utils.progressDialogdismiss(context);
                }

                @Override
                public void success(
                        RegistrationResponsModel regProfileResponse,
                        Response arg1) {
                    Utils.progressDialogdismiss(context);
                    UserResponse(regProfileResponse);
                }
            });
        }


    @POST("/service/update") // annotation used to post the data
    void postEditServiceData(@Body MultipartTypedOutput attachments, 
            Callback<RegistrationResponsModel> callback);

//以下是上传文件的方法

multipartTypedOutput.addPart("profile_doc",new TypedFile("multipart/form-data", postCurriculamFile));

//以下是上传多张图片的方法

    for (int i = 0; i < images.size(); i++) {
        multipartTypedOutput.addPart("image[]", images.get(i));
    }       

这似乎很有趣,但是postCurriculamFile方法是什么?我正在使用通常的图库意图来选择每个图像,你能指点一下吗? - H4F
1
postCurriculamFile是文档的路径,文件路径通过Intent获取。如果您要发布图片,则不需要此行。如果文件类型为"application/pdf"或"doc",则执行以下操作: Utils.savePreferences(context, "postservicefile", path); - Dinesh IT
谢谢回复,实际上我创建了一个Volley请求来获取参数,在其onResponse中使用Retrofit请求图像,它可以正常工作,但这是安全的代码吗? - H4F
实现看起来很好,代码也很安全,但从优化的角度考虑最好使用 RetroFit。你可以实现图片和参数请求的双重功效。 - Dinesh IT
很难理解,我很着急,它自己没能工作或者我无法使其工作。 - H4F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接