Skip to content
This repository was archived by the owner on Mar 16, 2019. It is now read-only.
This repository was archived by the owner on Mar 16, 2019. It is now read-only.

Uploading image to S3 using presigned URL fails on Android #425

Open
@robindowling

Description

@robindowling

I have an implementation using RNFetchBlob.fetch that works flawlessly for iOS but always fails on Android, and I've been banging my head against this wall for a few days now.

I am uploading an image to AWS S3 using a presigned URL. The presigned URL comes from my server and generates new URLs for each request. However, on Android S3 responds with SignatureDoesNotMatch. I have set permissions in my AndroidManifest.xml as well as getting 'granted' back from PermissionsAndroid.request.

This is a simplified version of my code. I removed event logging etc to make things clearer.

setImage(uploadUrl) {
    const options = {mediaType: 'photo', noData: true, maxWidth: 1920, maxHeight: 1920, quality: 0.2};

    const setImage = new Promise((resolve, reject) => {
        return ImagePicker.launchImageLibrary(options, (response) => resolve(response));
    }).then((response) => {
        if (response.didCancel) return;
        if (response.error) throw new Error(response.error);

        const body = 'RNFetchBlob-' + response.uri;
        RNFetchBlob.fetch('PUT', uploadUrl, {'Content-Type': ''}, body).then((result) => {
            console.log('imagepicker RESPONSE');
            console.log(response);
            console.log('BODY');
            console.log(body);
            console.log('UPLOADURL');
            console.log(uploadUrl);
            console.log('RNFetchBlob RESULT');
            console.log(result);
        }).catch((error) => console.log(error));
    }).catch((error) => console.log(error));
}

On iOS (device and simulator), as mentioned, everything works well.
On Android (simulator, Marshmallow 6.0, api 23), this produces the following output:

imagepicker RESPONSE
{
    fileName: "image-874f9bae-d686-4b4e-b89c-a83f3e02b578.jpg",
    fileSize: 46513,
    height: 1024,
    isVertical: true,
    originalRotation: 0,
    path: "/storage/emulated/0/Android/data/com.client/files/Pictures/image-874f9bae-d686-4b4e-b89c-a83f3e02b578.jpg",
    type: "image/jpeg",
    uri: "file:///storage/emulated/0/Android/data/com.client/files/Pictures/image-874f9bae-d686-4b4e-b89c-a83f3e02b578.jpg",
    width: 683
}

BODY
"RNFetchBlob-file:///storage/emulated/0/Android/data/com.client/files/Pictures/image-874f9bae-d686-4b4e-b89c-a83f3e02b578.jpg"

UPLOADURL
"https://REDACTED-FOR-GITHUB.s3.amazonaws.com/production/asset/2ea438b8-0ba1-4680-b040-5493db3aac26/--unverified?Signature=78gf5edjILenQfttVB8ehSO5pvDvo%3D&x-amz-acl=public-read&Expires=1499637874&AWSAccessKeyId=REDACTED-FOR-GITHUB"

RNFetchBlob RESULT
FetchBlobResponse {data: "<?xml version="1.0" encoding="UTF-8"?>↵<Error><Cod…519/AxHazwJv34A4oQzpAg20k53LEP4=</HostId></Error>", taskId: "q742yws2pngu48hzk5bbjg", type: "utf8", respInfo: Object, info: function…}array: function ()base64: function ()blob: function ()data: "<?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>REDACTED-FOR-GITHUB</AWSAccessKeyId><StringToSign>PUT↵↵application/octet-stream↵1499637117↵x-amz-acl:public-read↵/REDACTED-FOR-GITHUB.s3/production/asset/a0245dd0-f72d-4199-9d29-3bb4de45b19d/--unverified</StringToSign><SignatureProvided> 78gf5edjILenQfttVB8ehSO5pvDvo =</SignatureProvided><StringToSignBytes>50 55 54 0a 0a 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 2d 73 74 72 65 61 6d 0a 31 34 39 39 32 33 37 31 31 37 0a 78 2d 61 6d 7a 2d 61 63 6c 3a 70 75 62 6c 69 63 2d 72 65 61 64 0a 2f 6d 69 6e 75 74 65 73 2d 73 74 6f 72 61 67 65 2f 70 72 6f 64 75 63 74 69 6f 6e 2f 61 73 71 65 74 2f 61 30 32 34 35 64 64 30 2d 66 37 32 64 2d 34 31 39 39 2d 39 64 32 39 2d 33 62 62 34 64 65 31 35 62 31 39 64 2f 2d 2d 75 6e 76 65 72 45 66 69 65 64</StringToSignBytes><RequestId>BC2909B1F6FA5AB2</RequestId><HostId>H/lwKoVq0GCJB74bslVFiwPhHFZRopoUi7Iv6FDsH+N0519/AxHazwJv34A4oQzpAg20k53LEP4=</HostId></Error>"flush: function ()info: function ()json: function ()path: function ()readFile: function (encode)readStream: function (encode)respInfo: Objectsession: function (name)taskId: "q742yws2pngu48hzk5bbjg"text: function ()type: "utf8"__proto__: Object

Keep in mind that it seems unlikely that there is something wrong with the generated URL since it works 100% on iOS and 0% on Android.

Does anyone know what I'm doing wrong here?
Does anyone have a working solution for uploading images from library and camera on Android to S3 using a presigned URL?

Thank you 😌

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions