2017-09-01 231 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); 
相关问题