0

I am developing a React Native application and trying to upload an image stored on the device to S3. I know the path to the image but when I try to upload the image, S3 returns an unsupported file error or uploads the file with its name but the file only contains the file path string.

I am using aws-amplify to establish these connections.

Here is the code block that I use:

 const file = `${RNFetchBlob.fs.dirs.DocumentDir}/${localFilePath}`;
 Storage.put("exampleFolder/" + userId + ".jpeg", file)
                .then(result => console.log(result))
                .catch(err => console.log(err))

Many thanks

2 Answers 2

1

There's a nice example in the aws-mobile-react-native-starter repo. You just need to read the file, and then you can upload it.

return files.readFile(imagePath)
  .then(buffer => Storage.put(key, buffer, { level: 'private', contentType: result.type }))
  .then(fileInfo => ({ key: fileInfo.key }))
  .then(x => console.log('SAVED', x) || x);

To read the file they've used react-native-fetch-blob:

readFile(filePath) {
    return RNFetchBlob.fs.readFile(filePath, 'base64').then(data => new Buffer(data, 'base64'));
}
Sign up to request clarification or add additional context in comments.

Comments

1

You are sending the text as the content of the file, not file as in binary

Like below will store Hello in S3 file

Storage.put('test.txt', 'Hello')
    .then (result => console.log(result))
    .catch(err => console.log(err));  

Try mentioning contentType, for your case image/png, as in below example for text file

Storage.put('test.txt', 'Private Content', {
    level: 'private',
    contentType: 'text/plain'
})

Take inspiration from blow URLs:
https://viblo.asia/p/serverless-mobile-application-development-made-with-react-native-and-aws-mobilehub-Az45bnmQ5xY#11-add-source-code-15

https://gist.github.com/zeroFruit/d46d4cae57e5e8cf59e1b541c0bf322e

Code from first URL mentioned above

import Amplify, { API, Storage } from 'aws-amplify-react-native';
import RNFetchBlob from 'react-native-fetch-blob';
import ImagePicker from 'react-native-image-picker';

import { awsmobile } from './aws-exports'; // point path of aws-exports.js
import files from './files'; // point path of files.js

Amplify.configure(awsmobile);  


saveImage = () => {
  const options = {
    title: 'Select Avatar',
    storageOptions: {
      skipBackup: true,
      path: 'images'
    }
  };

  ImagePicker.showImagePicker(options, (response) => {
    console.log('Response = ', response);

    if (response.didCancel) {
      console.log('User cancelled image picker');
    }
    else if (response.error) {
      console.log('ImagePicker Error: ', response.error);
    }
    else if (response.customButton) {
      console.log('User tapped custom button: ', response.customButton);
    }
    else {
      RNFetchBlob
      .config({
        fileCache: true,
        appendExt: 'png',
      })
      .fetch('GET', response.uri, {
      })
      .then((res) => {
        // upload to storage
        files.readFile(res.data)
          .then(buffer => Storage.put('image.png', buffer, { level: 'public', contentType: 'image/png' }))
          .then(x => console.log('SAVED', x) || x);
      });
    }
  });
}

2 Comments

Thanks a lot. This solution also seems to work however @RadekCzemerys answer is more direct.
Yes, agree. Thanks for the comment. (Not a react guy, but a googler :p)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.