rn-fetch-blob icon indicating copy to clipboard operation
rn-fetch-blob copied to clipboard

Upload formData with S3 pre-signed URL

Open MayoudP opened this issue 5 years ago • 6 comments

Hello, first, here is the versions I'm using :

 "react": "16.9.0",
 "react-native": "0.61.5",
 "rn-fetch-blob": "^0.12.0"

I'm trying to upload a file using S3 and pre signed URL. I'm using rn-fetch-blob like this :

RNFetchBlob.fetch('POST', url, {
    'Content-Type' : 'multipart/form-data',
  }, [
    {
      name : name,
      filename: file.fileName,
      data: formData(fields)}
  ]).then((resp) => {
      console.log(resp);
    }).catch((err) => {
      // ...
      console.log("Catch error", err);
    })

where formData is basically a function returning a FormData() object containing all needed informations for S3 key, region, bucket, ....and the urlis the pre signed URL for S3 upload. However, by doing this, I'm getting a black screen, so I just wanted to know, if S3 upload (with pre signed method) was possible to achieve using rn-fetch-blob?

Any ideas, help, is very welcome. Thanks !

MayoudP avatar Jul 27 '20 12:07 MayoudP

Try application/octet-stream for your content-type header. What are you seeing in terms of errors? What are the contents of the actual file that was uploaded in S3?

justinmchase avatar Sep 16 '20 18:09 justinmchase

@MayoudP Hi, did you upload to s3 with the pre signed method finally? any code will be appreciated :) Thanks! @justinmchase

matamicen avatar Oct 06 '20 11:10 matamicen

{
  "rn-fetch-blob": 0.12.0,
  "react-native": 0.61.5
}

@matamicen This code works for both Android & iOS

const presignedUrl = "https://xxx.s3.amazonaws.com/abc.mp4?AWSAccessKeyId=xxx&Expires=xxx&Signature=xxx&x-amz-acl=public-read&x-amz-security-token=xxx";

const response = await RNFetchBlob.fetch(
  'PUT',
  presignedUrl,
  {
    'Content-Type': undefined
  },
  RNFetchBlob.wrap(file.path.replace('file://', '')),
)

Note 1. { 'Content-Type': undefined } is needed for iOS (works with Android) 2. file.path.replace('file://', '') is also needed for iOS (works with Android)

siriwatknp avatar Nov 03 '20 14:11 siriwatknp

RNFetchBlob.fetch(
                'PUT',
                link,
                {
                    'Content-Type': undefined
                },
                RNFetchBlob.wrap(Platform.OS === "android" ? this.selectedImage.uri : this.selectedImage.uri.replace("file://", "")),
            )
                .then((resp) => {
                    console.log("Response data", resp)
                    this.onImageUploadSuccess(resp)
                }).catch((err) => {
                    this.onUploadFailure(err)
                })
                
              **Above code worked for me**

manilbajracharya avatar Jan 03 '21 18:01 manilbajracharya

Hi @manilbajracharya @siriwatknp This is how I've implemented it:

s3.getSignedUrl('putObject', {
                    Key: 'responses/' + filename,
                    Body: file,
                    Bucket: AWScreds.bucketLanding,
                    Tagging: "tag"
                  }, (err, url) => {
                    if (url) {
                     
                      console.log("SIGNED URL", url);
                      // ========================Upload file========================
                      RNFetchBlob.fetch('PUT', url,
                        {
                          'Content-Type': undefined
                        },
                        RNFetchBlob.wrap(filePath))
                        .then((res) => {
                          console.log("Uploaded", res.text())
                        })
                        .catch((err) => {
                          console.log("Err", err);
                        });
                      // ========================Upload file========================
                    }

This throws no error in the console, but when I paste the signed url in the browser, this is what I see:

<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

RN version: 0.63.4 OS: Android Library version: ^0.12.0

Could you please let me know where I might be making a mistake? Thank you.

Balthazar33 avatar Jun 16 '21 05:06 Balthazar33

RNFetchBlob.fetch(
                'PUT',
                link,
                {
                    'Content-Type': undefined
                },
                RNFetchBlob.wrap(Platform.OS === "android" ? this.selectedImage.uri : this.selectedImage.uri.replace("file://", "")),
            )
                .then((resp) => {
                    console.log("Response data", resp)
                    this.onImageUploadSuccess(resp)
                }).catch((err) => {
                    this.onUploadFailure(err)
                })
                
              **Above code worked for me**

Thanks a lot this works you can also set filetype in content type it will work.

laxy7698 avatar Feb 04 '25 06:02 laxy7698