简体   繁体   English

使用Retrofit分段上传到Amazon S3

[英]Multipart Upload to Amazon S3 using Retrofit

I'm attempting to convert all my asynctasks and HttpPost code to use Retrofit, so far so good, but I'm having trouble uploading user files to an amazon s3 bucket. 我试图将我的所有asynctasks和HttpPost代码转换为使用Retrofit,到目前为止一直很好,但我在将用户文件上传到亚马逊s3存储桶时遇到问题。 The file upload has two parts: 文件上传包含两部分:

  1. Query api to get a upload_url and amazon upload params. 查询api以获取upload_url和amazon上传参数。
  2. Upload File to specified location with params provided in first call. 使用第一次调用中提供的参数将文件上载到指定位置。

Here's an example list of parameters provided to me from the first call. 这是第一次调用时提供给我的参数列表示例。 According to the documentation, these values can change or not be included, and the 2nd api call must call use these params in the exact order they were provided. 根据文档,这些值可以更改或不包括在内,第二个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"

In order to deal with the dynamic content. 为了处理动态内容。 I created a custom converter to have retrofit return me a LinkedHashMap in my first API call. 我创建了一个自定义转换器,让我在第一次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);    
}

Then in the second api call, Once I have these values I create a FormUrlEncodedTypedOutput by iterating over the HashMap and adding each item. 然后在第二个api调用中,一旦我有了这些值,我就通过迭代HashMap并添加每个项来创建一个FormUrlEncodedTypedOutput。

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

Everything up to here seems to be working. 到目前为止的一切似乎都在起作用。 I'm getting the necessary upload params and the ordering seems to be consistent. 我得到了必要的上传参数,订单似乎是一致的。 I'm a bit less sure about how I have my multipart retrofit call setup. 我对如何进行多部分改装呼叫设置不太确定。 I then use that inside a synchronous retrofit call inside an intentservice. 然后我在一个intentservice里面的同步改装调用中使用它。

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

This results in a Amazon error. 这会导致亚马逊错误。

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

I've been googling and it seems like Amazon prefers the "key" value to be first? 我一直在谷歌搜索,似乎亚马逊更喜欢“关键”价值是第一? However, if i put the "key" in front of "AWSAccessKeyId" I get a 403 unauthorized error. 但是,如果我把“密钥”放在“AWSAccessKeyId”前面,我会收到403未经授权的错误。 Do i have my retrofit call setup correctly? 我是否正确设置了改装呼叫? If someone could help me figure this out, I'd appreciate it. 如果有人可以帮我解决这个问题,我会很感激。 It's taken a few days to convert most of my uploading code over to retrofit and if I've been stuck on this for a while. 我花了几天的时间将我的大部分上传代码转换为改装,如果我已经坚持了一段时间。

Thanks! 谢谢!

Solution was to use a @PartMap instead of the FormUrlEncodedTypedOutput. 解决方案是使用@PartMap而不是FormUrlEncodedTypedOutput。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM