joltup / rn-fetch-blob

A project committed to making file access and data transfer easier, efficient for React Native developers.
MIT License
2.81k stars 772 forks source link

Upload formData with S3 pre-signed URL #632

Open MayoudP opened 3 years ago

MayoudP commented 3 years ago

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 !

justinmchase commented 3 years ago

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?

matamicen commented 3 years ago

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

siriwatknp commented 3 years ago
{
  "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)

  1. file.path.replace('file://', '') is also needed for iOS (works with Android)
manilbajracharya commented 3 years ago
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**
Balthazar33 commented 3 years ago

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.