2015-04-18 32 views
6

Tôi đang cố gắng chuyển đổi tất cả các asynctask và mã HttpPost của mình để sử dụng Retrofit, cho đến nay rất tốt, nhưng tôi đang gặp sự cố khi tải tệp người dùng lên thùng aazon s3. Tải lên tệp có hai phần:Multipart Tải lên Amazon S3 bằng Retrofit

  1. Truy vấn api để nhận thông số tải lên upload_url và amazon.
  2. Tải tệp lên vị trí được chỉ định bằng thông số được cung cấp trong cuộc gọi đầu tiên.

Dưới đây là danh sách ví dụ về các tham số được cung cấp cho tôi từ cuộc gọi đầu tiên. Theo tài liệu, các giá trị này có thể thay đổi hoặc không được bao gồm và cuộc gọi api thứ 2 phải gọi sử dụng các thông số này theo thứ tự chính xác mà chúng được cung cấp.

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

Để giải quyết nội dung động. Tôi đã tạo một công cụ chuyển đổi tùy chỉnh để trang bị thêm cho tôi một LinkedHashMap trong cuộc gọi API đầu tiên của tôi.

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

Sau đó, trong cuộc gọi api thứ hai, Khi tôi có các giá trị này, tôi tạo FormUrlEncodedTypedOutput bằng cách lặp qua HashMap và thêm từng mục.

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

Mọi thứ đến đây đều có vẻ hoạt động. Tôi nhận được các thông số tải lên cần thiết và thứ tự dường như nhất quán. Tôi là một chút ít chắc chắn về cách tôi có thiết lập cuộc gọi đa trang bị thêm của tôi. Sau đó tôi sử dụng nó bên trong một cuộc gọi retrofit đồng bộ bên trong một intentservice.

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

Điều này dẫn đến lỗi Amazon.

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

Tôi đã googling và có vẻ như Amazon thích giá trị "chìa khóa" đầu tiên? Tuy nhiên, nếu tôi đặt "khóa" ở phía trước "AWSAccessKeyId", tôi nhận được 403 lỗi trái phép. Tôi có cài đặt lại thiết bị gọi chính xác không? Nếu ai đó có thể giúp tôi hình dung ra điều này, tôi sẽ đánh giá cao điều đó. Mất một vài ngày để chuyển đổi hầu hết mã tải lên của tôi qua để trang bị thêm và nếu tôi bị kẹt trong thời gian này.

Cảm ơn!

+0

Bạn có thể hiển thị tất cả mã của mình nếu có thể tìm cách lấy thông tin được gửi lại từ phản hồi chữ ký của Amazon S3 – Lion789

Trả lời

4

Giải pháp là sử dụng một @PartMap thay vì FormUrlEncodedTypedOutput.

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

Hey bạn có ý tưởng nào về cách nhận yêu cầu đã ký từ trang bị thêm? Đây là câu hỏi của tôi về SO với nỗ lực của tôi http://stackoverflow.com/questions/30411672/how-to-add-nodejs-s3-heroku-direct-upload-to-android – Lion789

Các vấn đề liên quan