使用 Retrofit 分段上传到 Amazon S3

Multipart Upload to Amazon S3 using Retrofit

我正在尝试将我所有的异步任务和 HttpPost 代码转换为使用 Retrofit,到目前为止还不错,但是我在将用户文件上传到 amazon s3 存储桶时遇到了问题。 文件上传分为两部分:

  1. 查询 api 以获得 upload_url 和亚马逊上传参数。
  2. 使用第一次调用时提供的参数将文件上传到指定位置。

这是第一次通话时提供给我的参数列表示例。根据文档,这些值可以更改或不包含在内,第二次 api 调用必须按照提供的确切顺序调用使用这些参数。

"AWSAccessKeyId": "some_id",    
"key": "/users/1234/files/profile_pic.jpg",
"acl": "private",
"Filename": "profile_pic.jpg",
"Policy": "some_opaque_string",
"Signature": "another_opaque_string",
"Content-Type": "image/jpeg"

为了处理动态内容。我创建了一个自定义转换器,以便在我的第一个 API 调用中为我 return 改造一个 LinkedHashMap。

public class CustomConverter implements Converter {

@Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {       
        ...
        Type mapType = new TypeToken<LinkedHashMap<String, String>>(){}.getType();
        return new Gson().fromJson(JSON_STRING, mapType);    
}

然后在第二个 api 调用中,获得这些值后,我通过遍历 HashMap 并添加每个项目来创建 FormUrlEncodedTypedOutput。

FormUrlEncodedTypedOutput params = new FormUrlEncodedTypedOutput();
for (Map.Entry<String, String> entry : uploadParams.entrySet()) {
            params.addField(KEY, VALUE);
}

到目前为止一切似乎都在工作。我正在获取必要的上传参数,并且顺序似乎是一致的。我不太确定我的多部分改造调用设置是如何设置的。然后我在 intentservice 中的同步改造调用中使用它。

@Multipart
    @POST("/")
    Response uploadFile(@Part ("whatdoesthisdo?") FormUrlEncodedTypedOutput params, @Part("File") TypedFile file);

这会导致亚马逊错误。

"code" : "InvalidArgument"
"message" : "Bucket POST must contain a field named 'key'.  If it is specified, please check the order of the fields."

我一直在谷歌搜索,亚马逊似乎更喜欢 "key" 值放在第一位?但是,如果我将 "key" 放在 "AWSAccessKeyId" 前面,我会收到 403 未经授权的错误。我的改装呼叫设置是否正确?如果有人可以帮助我解决这个问题,我将不胜感激。我花了几天时间将我的大部分上传代码转换为改造,如果我已经坚持了一段时间。

谢谢!

解决方案是使用 @PartMap 而不是 FormUrlEncodedTypedOutput。

@Multipart
@POST("/")
Response uploadFile(@PartMap LinkedHashMap<String,String> params, @Part("File") TypedFile file);