2017-09-01 208 views
0

我試圖使用預先簽名的URL將文件上傳到Amazon S3。我從生成URL的服務器獲取URL &將它作爲JSON對象的一部分發送給我。我得到的URL爲字符串,像這樣:使用Retrofit2將文件上傳到AWS S3預簽名的URL

https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/ImageName?X-Amz-Security-Token=xxfooxx%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Fxxbarxx%3D&X-Amz-Algorithm=xxAlgoxx&X-Amz-Date=20170831T090152Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=xxcredxx&X-Amz-Signature=xxsignxx

不幸的是,當我通過這Retrofit2,它修改字符串試圖使之成爲一個URL。我已經設置了encoding=true,這些問題涉及大多數問題,但並不完全。我知道該字符串按原樣運行。我已經試過它在郵差&獲得成功的迴應。

月1日我試圖只是把字符串(除了我切出的baseUrl)作爲一個整體進入路徑

public interface UpdateImageInterface { 
    @PUT("{url}") 
    Call<Void> updateImage(@Path(value="url", encoded=true) String url, Body RequestBody image); 
} 

調用代碼:

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/") 
      .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is "ImageName..." 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

這個工程主要是除'?' (在「ImageName」之後)轉換爲「%3F」。這會導致Bad Request/400.

我的下一個嘗試是使用Retrofit2創建查詢,但將整個String(包含多個查詢)轉儲到查詢中。

public interface UpdateImageInterface { 
    @PUT("ImageName") 
    Call<Void> updateProfilePhoto(@Query(value="X-Amz-Security-Token", encoded = true) String token, @Body RequestBody image); 
} 

調用代碼:

Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/") 
      .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is "xxfooxx..." 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

這得到了 '?'正確的渲染,但所有的「&」得到改爲「%26」

最後我想經過整串在baseUrl()但是,讓一個IllegalArgumentException因沒有「/」就結束。

我知道我可以解析預簽名的URL,使多個查詢&在Retrofit2中組裝它們,因爲查詢應該完成,但我想避免這種處理。

要重申的問題:

有沒有一種方法可以輕鬆地(沒有繁重的字符串解析)將文件上傳到S3使用Retrofit2預先簽署的網址?

+0

圖書館,或者它依賴的東西似乎有點破碎。看看這裏的評論:https://github.com/square/retrofit/issues/1199 ...特別注意最後一個。 –

+0

@ Michael-sqlbot是的,這聽起來像是同樣的問題。我找到了一個解決方案(也許更多的解決方法?)。我會在幾天後得到一些時間後發佈。 – Gary99

回答

1

在同事的幫助下,這是解決方案。

public interface UpdateImageInterface { 
    @PUT 
    Call<Void> updateImage(@Url String url, @Body RequestBody image); 
} 

調用代碼:

/* since the pre-signed URL from S3 contains a host, this dummy URL will 
    * be replaced completely by the pre-signed URL. (I'm using baseURl(String) here 
    * but see baseUrl(okhttp3.HttpUrl) in Javadoc for how base URLs are handled 
    */ 
    Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl("http://www.dummy.com/") 
     .build(); 

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class); 
    // imageUrl is the String as received from AWS S3 
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile); 

Javadoc的信息上@Url(類URL)& baseUrl()(類Retrofit.Builder)

0

使用,而使用presigned URL直接上傳到S3以下。

@Multipart 
@PUT 
@Headers("x-amz-acl:public-read") 
Call<Void> uploadFile(@Url String url, @Header("Content-Type") String contentType, @Part MultipartBody.Part part); 
相關問題