我正在尝试使用预先签名的URL将文件上传到亚马逊的S3。我从服务器获取URL,该服务器生成URL并将其作为JSON对象的一部分发送给我。我将URL作为String获取,如下所示:
不幸的是,当我将它传递给Retrofit2时,它会修改String,试图将其变为URL。我设置了encoding=true
,它解决了大部分问题,但并未完全解决。我知道String的工作原理。我在Postman尝试了它并得到了成功的回复。
第一次我尝试将String(除了我作为baseUrl剪掉的东西)作为一个整体放入Path中
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”。这会导致错误的请求/ 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()
中传递整个String但是由于最后没有'/'而给出IllegalArgumentException。
我知道我可以解析预先签名的URL以进行多次查询并在Retrofit2中组装它们,因为查询应该完成,但我想避免这种处理。
重申一下这个问题:
有没有办法轻松(没有繁重的字符串解析)使用Retrofit2将文件上传到带有预签名URL的S3?
在同事的帮助下,这就是解决方案。
public interface UpdateImageInterface {
@PUT
Call<Void> updateImage(@Url String url, @Body RequestBody image);
}
来电代码:
String CONTENT_IMAGE = "image/jpeg";
File file = new File(localPhotoPath); // create new file on device
RequestBody requestFile = RequestBody.create(MediaType.parse(CONTENT_IMAGE), file);
/* 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)的信息
MediaType
是OkHttp库中的一个类,通常与Retrofit(均来自Square)一起使用。有关传递给parse方法的常量的信息可以在Javadoc中找到。
使用预签名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);