如何询问Retrofit2,不对我的动态URL进行编码?

问题描述 投票:0回答:1

我正在尝试将我的代码库从Retrofit 1.9升级到2.0版。在版本1.9中上传图像没有问题。但是,在将其更改为2.0版之后,我收到了S3响应错误。

这是我在Retrofit v1.9中上传图片的界面:

public interface IFileUploadAPI
{
    @PUT("/{url}")
    void uploadFile(@Path(value = "url", encode = false) String url, @Body() TypedFile file,
                    Callback<UploadFileResponse> callback);
}

我已将其更改为Retrofit v2.0上的以下代码:

public interface IFileUploadAPI
{
    @PUT
    Call<UploadFileResponse> uploadFile(@Url String url, @Body RequestBody file);
}

我正在以这种方式实施它。

public class MyFileUploadAPI
{
    private IFileUploadAPI mService;

    public MyFileUploadAPI()
    {
        final Retrofit adapter = new Retrofit.Builder() //
                        .baseUrl(MyAPIConstant.API_URL_BASE) // This URL will be ignored as we are using dynamic url. So no matters what it is.
                        .addConverterFactory(GsonConverterFactory.create(GsonUtils.getGson())) //
                        .client(ASDKApplication.getInstance().getOkHttpClient()) //
                        .build();

        this.mService = adapter.create(IFileUploadAPI.class);
    }

    public void uploadFile(final String url, final String filePath, final String mimeType)
    {
        RequestBody file = RequestBody.create(MediaType.parse(mimeType), filePath);
        Call<UploadFileResponse> call = mService.uploadFile(url, file);
                call.enqueue(new Callback<HitchUploadFileResponse>()
        {
            @Override
            public void onResponse(Call<UploadFileResponse> call, Response<UploadFileResponse> response)
            {
                UploadFileResponse uploadFileResponse = new UploadFileResponse();

                if (response.isSuccessful() && response.body() != null)
                {
                    uploadFileResponse = response.body();
                }

                // Rest of code...
            }

            @Override
            public void onFailure(Call<UploadFileResponse> call, Throwable t)
            {
                Logger.error(TAG, "uploadFile.onFailure(), msg: " + t.getMessage());
            }
        }
    }
}

因此,当用户点击Upload按钮时,我调用一个API,它会返回一个我必须调用的URL。回应看起来像:

[{"uploadSignedURL":"https://my-account.s3.amazonaws.com/license/1000_front_1464988248.jpeg?AWSAccessKeyId=MY_ID\u0026Expires=1464991848\u0026Signature=NhStdEX8RH3J0uzvVa6h%2FvN6FZQ%3D","filePath":"license/1000_front_1464988248.jpeg","target":"driving_license_front_img"}]

最后响应上面的url调用(http状态代码403禁止):

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>MY_ID</AWSAccessKeyId><StringToSign>PUT

image/jpeg; charset=utf-8
1464991848
/my-account/license/1000_front_1464988248.jpeg</StringToSign><SignatureProvided>NhStdEX8RH3J0uzvVa6h/vN6FZQ=</SignatureProvided><StringToSignBytes>50 55 54 0a 0a 69 6d 61 67 65 2f 6a 70 65 67 3b 20 63 68 61 72 73 65 74 3d 75 74 66 2d 38 0b 31 34 36 34 39 39 31 38 34 38 0a 2f 6d 79 74 65 6b 73 69 3a 67 72 61 62 68 69 45 63 68 2f 6c 69 63 65 6e 73 65 2f 31 30 30 30 5f 66 72 6f 6e 74 5f 31 34 36 34 39 38 38 32 34 38 2e 6a 70 65 67</StringToSignBytes><RequestId>2D6D08FE4E34FCE5</RequestId><HostId>tpvmJdeRxtAzPxOk2zFwMF2Ne6hmNMkcaM9D7m/I13iynYGJyqtC0U72B2t41SDYfPBjCRTVyOY=</HostId></Error>
android amazon-s3 retrofit2
1个回答
0
投票

好的,我发现了什么是错的。

okhttp正在将charset=utf-8添加到我的contentType中。因此我的contentType就像这个contentType: image/jpeg; charset=utf-8。我在Postman上测试并通过删除; charset=utf-8我能够上传我的图像。

https://stackoverflow.com/a/25560731/513413说添加charset的原因。这是因为我正在将路径传递给我的图像文件。你可以轻松改变

RequestBody file = RequestBody.create(MediaType.parse(mimeType), filePath);

RequestBody file = RequestBody.create(MediaType.parse(mimeType), new File(filePath));

还有一件更重要的事情。将图像上传到S3后,Amazon会返回空状态的HTTP状态代码200。所以你也必须改变界面。

public interface IFileUploadAPI
{
    @PUT
    Call<Void> uploadFile(@Url String url, @Body RequestBody file);
}
© www.soinside.com 2019 - 2024. All rights reserved.