使用Retrofit分段上传到Amazon S3

and*_*ent 7 android amazon-s3 retrofit

我试图将我的所有asynctasks和HttpPost代码转换为使用Retrofit,到目前为止一直很好,但我在将用户文件上传到亚马逊s3存储桶时遇到问题.文件上传包含两部分:

  1. 查询api以获取upload_url和amazon上传参数.
  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"
Run Code Online (Sandbox Code Playgroud)

为了处理动态内容.我创建了一个自定义转换器,让我在第一次API调用中返回一个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);    
}
Run Code Online (Sandbox Code Playgroud)

然后在第二个api调用中,一旦我有了这些值,我就通过迭代HashMap并添加每个项来创建一个FormUrlEncodedTypedOutput.

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

到目前为止的一切似乎都在起作用.我得到了必要的上传参数,订单似乎是一致的.我对如何进行多部分改装呼叫设置不太确定.然后我在一个intentservice里面的同步改装调用中使用它.

@Multipart
    @POST("/")
    Response uploadFile(@Part ("whatdoesthisdo?") FormUrlEncodedTypedOutput params, @Part("File") TypedFile file);
Run Code Online (Sandbox Code Playgroud)

这会导致亚马逊错误.

"code" : "InvalidArgument"
"message" : "Bucket POST must contain a field named 'key'.  If it is specified, please check the order of the fields."
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

and*_*ent 4

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

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