小编典典

使用 Retrofit 2.0 发布多部分表单数据,包括图像

all

我正在尝试使用 Retrofit 2.0对服务器进行 HTTP POST

MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain");
MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG,90,byteArrayOutputStream);
profilePictureByte = byteArrayOutputStream.toByteArray();

Call<APIResults> call = ServiceAPI.updateProfile(
        RequestBody.create(MEDIA_TYPE_TEXT, emailString),
        RequestBody.create(MEDIA_TYPE_IMAGE, profilePictureByte));

call.enqueue();

服务器返回一个错误,指出该文件无效。

这很奇怪,因为我尝试在 iOS 上上传相同格式的相同文件(使用其他库),但上传成功。

我想知道使用 Retrofit 2.0 上传图片的正确方法是什么?

在上传之前我应该​​先将其保存到磁盘吗?

PS:我已经对其他不包含图像的多部分请求进行了改造,并且他们成功完成了。问题是当我试图在正文中包含一个字节时。


阅读 57

收藏
2022-07-30

共1个答案

小编典典

我强调 1.9 和 2.0 中的解决方案,因为它对某些人有用

1.9中,我认为更好的解决方案是将文件保存到磁盘并将其用作 Typed 文件,例如:

改装 1.9

(我不知道你的服务器端实现)有一个类似于这个的API接口方法

@POST("/en/Api/Results/UploadFile")
void UploadFile(@Part("file") TypedFile file,
                @Part("folder") String folder,
                Callback<Response> callback);

并像使用它一样

TypedFile file = new TypedFile("multipart/form-data",
                                       new File(path));

对于 RetroFit 2 使用以下方法

RetroFit 2.0(这是RetroFit 2

问题的解决方法,现在已修复,正确的方法请参考jimmy0251
的答案

API接口:

public interface ApiInterface {

    @Multipart
    @POST("/api/Accounts/editaccount")
    Call<User> editUser(@Header("Authorization") String authorization,
                        @Part("file\"; filename=\"pp.png\" ") RequestBody file,
                        @Part("FirstName") RequestBody fname,
                        @Part("Id") RequestBody id);
}

像这样使用它:

File file = new File(imageUri.getPath());

RequestBody fbody = RequestBody.create(MediaType.parse("image/*"),
                                       file);

RequestBody name = RequestBody.create(MediaType.parse("text/plain"),
                                      firstNameField.getText()
                                                    .toString());

RequestBody id = RequestBody.create(MediaType.parse("text/plain"),
                                    AZUtils.getUserId(this));

Call<User> call = client.editUser(AZUtils.getToken(this),
                                  fbody,
                                  name,
                                  id);

call.enqueue(new Callback<User>() {

    @Override
    public void onResponse(retrofit.Response<User> response,
                           Retrofit retrofit) {

        AZUtils.printObject(response.body());
    }

    @Override
    public void onFailure(Throwable t) {

        t.printStackTrace();
    }
});
2022-07-30