我正在try 使用Retrofit 2.0向服务器发送HTTP帖子

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

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

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

我想知道用Retrofit 2.0上传照片的正确方式是什么?

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

附注:我已经对其他不包括图像的多部分请求使用了改装,他们成功地完成了.问题是当我试图在正文中包含一个字节时.

推荐答案

我在1.9和2.0中都强调了这个解决方案,因为它对一些人很有用

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

改装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));

对于改装2,请使用以下方法

RetroFit 2.0 ( This was a workaround for an issue in RetroFit 2 which is fixed now, for the correct method refer jimmy0251's answer)

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

Android相关问答推荐

渠道与共享流有什么区别

使用kotlin kotlinx序列化与generic

周期性工作请求状态停留在排队处

如何在Android Room中使用@Relation多对一查询

NativeScript在`ns run android`上重复Kotlin类

保护所有程序包文件和类

如何从LazyColumn中的图标异步获取可绘制的加载?

Android 11:在try 获取文件的永久权限后,仍然没有读写权限

如何解决Gradle构建错误:java.lang.NoSuchMethodError

Jetpack Compose:如何将文本放置在行的右侧?

从不可组合回调打开可组合屏幕

在 kotlin 上向适配器添加绑定视图功能

了解 CoroutineScope(Job() + Dispatchers.Main) 语法

面向Jetpack Compose的可组合放置问题

为什么我收到这个错误我需要安装 android studio

Jetpack Compose:在屏幕外制作长水平图像的动画

如何在 Jetpack Compose 中创建无限pager

如何在 Dolphin 中启用 android studio new logcat | 2021.3.1 金丝雀 6?

是什么让 Android Studio 中的按钮变成紫色?加上新手的其他奇怪行为

为什么在try 实例化 Mediaplayer 时会出现 NullPointerException?安卓Kotlin