0

I am trying to upload image to amazon s3,If possible can any one provide links /docs for how to upload to amazon s3, any help much appreciated

Hussian Shaik
  • 2,559
  • 9
  • 37
  • 57
  • break down your problem into smaller parts and work each one out. 1) Networking in react-native. 2) Uploading file in react-native network framework. 3) Amazon S3 API. Also, I am not sure this question is good for SO. – Poutrathor Mar 08 '16 at 14:02
  • Are you able to share what solution you ended up using? – Marklar Apr 11 '17 at 10:34

3 Answers3

3

S3 options:

    // this.state.s3options in YourComponent
    {
      "url": "https://yourapp.s3.eu-central-1.amazonaws.com",
      "fields": {
        "key": "cache/22d65141b48c5c44eaf93a0f6b0abc30.jpeg",
        "policy": "eyJleHBpcm...1VDE0Mzc1OVoifV19",
        "x-amz-credential": "AK...25/eu-central-1/s3/aws4_request",
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-date": "20161125T143759Z",
        "x-amz-signature": "87863c360...b9b304bfe650"
      }
    }

Component:

    class YourComponent extends Component {
      // ...
    
      // fileSource looks like: {uri: "content://media/external/images/media/13", isStatic: true}
      async uploadFileToS3(fileSource) {
        try {
          var formData = new FormData();
          // Prepare the formData by the S3 options
          Object.keys(this.state.s3options.fields).forEach((key) => {
            formData.append(key, this.state.s3options.fields[key]);
          });
          formData.append('file', {
            uri: fileSource.uri,
            type: 'image/jpeg',
          });
          formData.append('Content-Type', 'image/jpeg')
    
          var request = new XMLHttpRequest();
          request.onload = function(e) {
            if (e.target.status === 204) {
              // Result in e.target.responseHeaders.Location
              this.setState({avatarSourceRemote: {uri: e.target.responseHeaders.Location}})
            }
          }.bind(this)
          request.open('POST', this.state.s3options.url, true);
          request.setRequestHeader('Content-type', 'multipart/form-data');
          request.send(formData);
        } catch(error) {
          console.error(error);
        }
      }
    
      // Example display the uploaded image
      render() {
        if (this.state.avatarSourceRemote) {
          return (
            <Image source={this.state.avatarSourceRemote} style={{width: 100, height: 100}} />
          );
        } else {
          return (
            <Text>No Image</Text>
          );
        }
      }
    }
lowercase00
  • 1,917
  • 3
  • 16
  • 36
blackchestnut
  • 1,259
  • 10
  • 15
1

This works for me

import fs from 'react-native-fs';
import {decode} from 'base64-arraybuffer';
import AWS from 'aws-sdk';

export const uploadFileToS3 = async (file) => {

  const BUCKET_NAME = 'XXXXXXXXXX';
  const IAM_USER_KEY = 'XXXXXXXXXX';
  const IAM_USER_SECRET = 'XXXXXXXXXXXXXXX';

  const s3bucket = new AWS.S3({
    accessKeyId: IAM_USER_KEY,
    secretAccessKey: IAM_USER_SECRET,
    Bucket: BUCKET_NAME,
    signatureVersion: 'v4',
  });

  const contentType = file.type;
  const contentDeposition = `inline;filename="${file.name}"`;
  const fPath = file.uri;
  const base64 = await fs.readFile(fPath, 'base64');
  const arrayBuffer = decode(base64);

  return new Promise((resolve, reject) => {
    s3bucket.createBucket(() => {
      const params = {
        Bucket: BUCKET_NAME,
        Key: file.name,
        Body: arrayBuffer,
        ContentDisposition: contentDeposition,
        ContentType: contentType,
      };
      s3bucket.upload(params, (error, data) => {
        utils.stopLoader();
        if (error) {
          reject(getApiError(error));
        } else {
          console.log(JSON.stringify(data));
          resolve(data);
        }
      });
    });
  });
};
lowercase00
  • 1,917
  • 3
  • 16
  • 36
Rajesh N
  • 6,198
  • 2
  • 47
  • 58
0

This worked for me after a significant amount of trying over and over again... I am also using a lambda function to serve me the link to post with. The lambda function is just using getSignedUrl.

// Lambda Function
const AWS = require('aws-sdk')

AWS.config.update({
    accessKeyId: {bucket_access},
    secretAccessKey: {bucket_secret},
    signatureVersion: 'v4',
    region: {bucket_region}
})

const s3 = new AWS.S3()

exports.handler = async (event) => {
    
    const URL = s3.getSignedUrl('putObject', {Bucket: {bucket_name}, 
        
    // name of file name being placed in S3 Bucket
    // event === metaData object
    Key: `${event.{key}}/photo00`})
    
    return URL
};


// React Native
const imagePreview = '{image_uri}'
    
const handleURL = async () => {

    // metaData object
    const obj = {
        key: "meta_data"
    }

    const response = await fetch{{lambda_func_endpoint}, {
        method: 'POST',
        body: JSON.stringify(obj)
    })
    
    const json = await response.json();

    return json
}

const handleUpload = async () => {

    const URL = await handleURL()

    const imageExt = imagePreview.split('.').pop()

    // I have no idea why you are supposed to fetch before fetching...
    // makes no sense. But it works. Lots of trying as I said.
    let image = await fetch(imagePreview)

    // I have no idea why it needs to be a blob in order
    // to upload... makes no sense.
    image = await image.blob()

    await fetch(URL, {
        method: 'PUT',
        body: image,
        headers: {
            Accept: `image/${imageExt}`,
            'Content-Type': `image/${imageExt}`
        }
    })
    .then((res) => console.log(JSON.parse(JSON.stringify(res)).status))
    .catch((err) => console.error(err))

}

Let me know what you guys think!

le_don
  • 1
  • 1