使用 Retrofit2 将文件上传到 AWS S3 预签名 URL [英] Upload a file to AWS S3 pre-signed URL using Retrofit2

查看:40
本文介绍了使用 Retrofit2 将文件上传到 AWS S3 预签名 URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用预签名 URL 将文件上传到 Amazon 的 S3.我从生成 URL 的服务器获取 URL &将它作为 JSON 对象的一部分发送给我.我以字符串形式获取 URL,如下所示:

I'm trying to upload a file to Amazon's S3 using a pre-signed URL. I get the URL from a server which generates the URL & sends it to me as part of a JSON object. I get the URL as a String, something like this:

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-SignedHeaderhost&X-Amz-Expires=3600&X-Amz-Credential=xxcredxx&X-Amz-Signature=xxsignxx

不幸的是,当我将它传递给 Retrofit2 时,它会修改 String 以使其成为 URL.我已经设置了 encoding=true ,它解决了大部分问题,但并没有完全解决.我知道字符串按原样工作.我已经在 Postman & 中试过了获得成功的响应.

Unfortunately, when I pass this to Retrofit2, it modifies the String attempting to make it into a URL. I've set encoding=true which took care of most of the problem but not completely. I know the String works as it is. I've tried it in Postman & get a successful response.

首先,我尝试将字符串(除了我切出的 baseUrl 之外)作为一个整体放入路径

1st I tried just putting the String (except for what I cut out as baseUrl) as a whole into the 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.

This works mostly except the the '?' (after "ImageName") get converted to "%3F". This causes a Bad Request / 400.

我的下一次尝试是使用 Retrofit2 创建一个查询,然后将整个字符串(带有多个查询)转储到查询中.

My next attempt was to create a query with Retrofit2 but then dump the whole String (with multiple queries) into the query.

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"

This gets the '?' rendered correctly but all of the '&' get changed to "%26"

最后,我尝试在 baseUrl() 中传递整个字符串,但由于末尾没有 '/' 会导致 IllegalArgumentException.

Lastly I tried passing the whole String in baseUrl() but that gives an IllegalArgumentException for not having '/' on the end.

我知道我可以解析预先签名的 URL 以进行多个查询 &在 Retrofit2 中组装它们,因为应该完成查询,但我想避免这种处理.

I know that I could parse the pre-signed URL to make multiple queries & assemble them in Retrofit2 as queries should be done but I'd like to avoid that processing.

重申问题:

有没有一种方法可以使用 Retrofit2 使用预签名 URL 轻松(无需大量字符串解析)将文件上传到 S3?

Is there a way to easily (without heavy String parsing) upload a file to S3 with a pre-signed URL using Retrofit2?

推荐答案

在同事的帮助下,这是解决方案.

With help from a colleague, this is the solution.

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 的信息(类网址) &baseUrl()(类 Retrofit.Builder)

Javadoc for info on @Url (class Url) & baseUrl() (class Retrofit.Builder)

MediaTypeOkHttp 库中经常使用的一个类与改造(均来自 Square).可以在 Javadoc 中找到有关传递给 parse 方法的常量的信息.

MediaType is a class in the OkHttp library that is often used with Retrofit (both from Square). Info about constants passed to the parse method can be found in the Javadoc.

这篇关于使用 Retrofit2 将文件上传到 AWS S3 预签名 URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆