8

I have an image. I want to upload it to S3 using aws-amplify. All the Storage class upload examples are using text documents; however, I would like to upload an image. I am using expo which does not have support from react-native-fetch-blob, and react native does not have blob support... yet.

So my options seem to be:

  1. Create a node service via lambda.
  2. Upload only the base64 info to S3 and not a blob.

const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); if (status === 'granted') { const image = await ImagePicker.launchImageLibraryAsync({ quality: 0.5, base64: true }); const { base64 } = image; Storage.put(`${username}-profileImage.jpeg`, base64); }

Is this Correct?

Sequential
  • 1,455
  • 2
  • 17
  • 27

3 Answers3

14

EDIT FOR UPDATED ANSWER WITH RN BLOB SUPPORT VERSION: I have been able to solve this now that React Native has announced blob support and now we only need the uri. See the following example:

uploadImage = async uri => {
  const response = await fetch(uri);
  const blob = await response.blob();
  const fileName = 'profileImage.jpeg';
  await Storage.put(fileName, blob, {
    contentType: 'image/jpeg',
    level: 'private'
  }).then(data => console.log(data))
    .catch(err => console.log(err))
}

Old Answer

For all you get to this. I ended up using https://github.com/benjreinhart/react-native-aws3 This worked perfectly! But not the preferred solution as I would like to use aws-amplify.

Sequential
  • 1,455
  • 2
  • 17
  • 27
  • their documentation is not very helpful to perform such an easy task. Interesting discussion related to this issue also found in here: https://github.com/aws-amplify/amplify-js/issues/576 – Dr. Younes Henni Oct 23 '18 at 12:44
  • @Seuential: can you show me more details about the code. I follow the React Native code from https://aws-amplify.github.io/docs/js/storage#put but no hope – Luong Truong Nov 12 '18 at 07:33
  • @LuongTruong Are you getting an error message? This is really all the code relevant to the problem. – Sequential Nov 12 '18 at 19:37
  • @Sequential: thank you for your quick comment. I create a question on stackoverfow: https://stackoverflow.com/questions/53260500/react-native-upload-video-to-aws-s3-storage-using-aws-amplify. There is an error using the code, hope you can take a look and help me out. Thank you in advance! – Luong Truong Nov 13 '18 at 03:20
  • @LuongTruong What version of RN do you have? – Sequential Nov 13 '18 at 04:01
  • @Sequential: I am using react native 0.57.4 – Luong Truong Nov 13 '18 at 04:09
  • @Sequential: Did you try with the RN 0.57.4? This issue is still bothering me. Please let me know if you can solve it – Luong Truong Nov 15 '18 at 02:43
  • @LuongTrong I wonder 9f this is an issue with latest react/expo code looks fine. – Sequential Nov 19 '18 at 09:18
3

I would like to add a more complete answer to this question.

The below code allows to pick images from the mobile device library using ImagePicker from Expo and store the images in S3 using Storage from AWS Amplify.

import React from 'react';
import { StyleSheet, ScrollView, Image, Dimensions } from 'react-native'
import { withAuthenticator } from 'aws-amplify-react-native'
import { ImagePicker, Permissions } from 'expo'
import { Icon } from 'native-base'

import Amplify from '@aws-amplify/core'
import Storage from '@aws-amplify/storage'
import config from './aws-exports'

Amplify.configure(config)

class App extends React.Component {
  state = {
    image: null,
  }

  // permission to access the user's phone library
  askPermissionsAsync = async () => {
    await Permissions.askAsync(Permissions.CAMERA_ROLL);
  }

  useLibraryHandler = async () => {
    await this.askPermissionsAsync()
    let result = await ImagePicker.launchImageLibraryAsync(
      {
        allowsEditing: false,
        aspect: [4, 3],
      }
    )

    console.log(result);

    if (!result.cancelled) {
      this.setState({ image: result.uri })
      this.uploadImage(this.state.image)
    }
  }

  uploadImage = async uri => {
    const response = await fetch(uri);
    const blob = await response.blob();
    const fileName = 'dog77.jpeg';
    await Storage.put(fileName, blob, {
      contentType: 'image/jpeg',
      level: 'public'
    }).then(data => console.log(data))
      .catch(err => console.log(err))
  }

  render() {
    let { image } = this.state
    let {height, width} = Dimensions.get('window')
    return (
      <ScrollView style={{flex: 1}} contentContainerStyle={styles.container}>
        <Icon 
          name='md-add-circle'
          style={styles.buttonStyle}
          onPress={this.useLibraryHandler}
        />
        {image &&
          <Image source={{ uri: image }} style={{ width: width, height: height/2 }} />
        }
      </ScrollView>
    );
  }
}

export default withAuthenticator(App, { includeGreetings: true })

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
  buttonStyle: {
    fontSize: 45, 
    color: '#4286f4'
  }
});
Dr. Younes Henni
  • 1,613
  • 1
  • 18
  • 22
  • I use your code. The app is able to login, choose the picture. However, after receive the picture there is a warning "Network request failed". I think it comes from `const response = await fetch(uri);` I am using Expo 31.0.2. The same thing happen in Mr. @Sequential code. – Luong Truong Nov 13 '18 at 04:48
  • check this thread: https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed – Dr. Younes Henni Nov 13 '18 at 09:16
  • I run your example on Android and the link is "https://static.asiachan.com/Berry.Good.600.42297.jpg". I think it is not the `https` problem. Do you have any suggestion? I am willing to hear from you – Luong Truong Nov 14 '18 at 14:20
  • downgrade to expo version 30.0.1. My code does not seem to function properly on expo 31. Also make sure to install "rn-fetch-blob": "^0.10.13" and "buffer": "^5.2.1" using npm. I am happy to provide my package.json if you provide another communication way. – Dr. Younes Henni Nov 16 '18 at 12:49
-1

You can pass file object to .put method

Storage.put('test.png', file, { contentType: 'image/png' })
  .then (result => console.log(result))
  .catch(err => console.log(err));
Richard Zhang
  • 350
  • 1
  • 4
  • 2
    This does not work because a file object is reliant on Blob, but Blob is not yet supported in React Native, so it errors out unless I'm mistaken. – Sequential Mar 20 '18 at 18:01