How to upload image from library or camera with CRNA
CRNA (create react native app ) works with expo, so I will demo an example help you open library from your device or open camera, take a photo and upload to server. In this post, I only demo front end with react native. Display the system UI for choosing an image or a video from the phone’s ...
CRNA (create react native app ) works with expo, so I will demo an example help you open library from your device or open camera, take a photo and upload to server. In this post, I only demo front end with react native. Display the system UI for choosing an image or a video from the phone’s library you need use ImagePicker In Screen component, prepare a component like that
import React, { Component } from 'react' import { ImagePicker, FileSystem } from 'expo' import { View, Button } from 'react-native' export class HomeScreen extends Component constructor(props) { super(props) this.state = { imageUrl: 'https://sigma-static-files.imgix.net/default_profile_pic.png' } } render() { return() { <View> <Image source={{uri: this.state.imageUrl}} /> <Button onPress={this.takePhoto} title={'Take a photo'} /> <Button onPress={this.choosePhoto} title={'Choose a photo'} /> </View> } }
After that, do funtions to open library or open camera (note that simulator doesn't support test open camera, you need to test this on a real device) This is a function open camera
takePhoto = async () => { let pickerResult = await ImagePicker.launchCameraAsync({ exif: true, allowsEditing: true, quality: 0.7, base64: true, aspect: [4, 3] }) }
This is a function open library
choosePhoto = async () => { let pickerResult = await ImagePicker.launchImageLibraryAsync({ exif: true, allowsEditing: false, quality: 0.7, base64: true }) }
It returns infomation of an image with:
- cancelled: false => it means you chosed an image (not cancel when open library)
- uri: file:///.... => absolute path of image
- witdh: number
- height: number
- base64: //string too long => this string contains the image jpeg data Handle upload an image to server, depends on type of data that backend require, you need upload a right type. This is an example upload file with binary type
handleUploadPhoto = pickerResult => { const userId = this.props.account.rawId, { uploadAvatarProcessing } = this.props, cropInfo = { x: pickerResult.awidth / 2 - 301, // get center image y: pickerResult.height / 2 - 301, awidth: 602, height: 602 }, contentType = 'image/jpeg', fileName = pickerResult.uri.split('/').pop() FileSystem.getInfoAsync(pickerResult.uri).then(info => { uploadAvatarProcessing( userId, fileName, contentType, info.size, cropInfo, pickerResult ) }) }
I use sagas and apisauce to help upload image. Finish, you call handleUploadPhoto at each function get image from your device.
takePhoto = async () => { let pickerResult = await ImagePicker.launchCameraAsync({ exif: true, allowsEditing: true, quality: 0.7, base64: true, aspect: [4, 3] }) if (!pickerResult.cancelled) { this.handleUploadPhoto(pickerResult) } } choosePhoto = async () => { let pickerResult = await ImagePicker.launchImageLibraryAsync({ exif: true, allowsEditing: false, quality: 0.7, base64: true }) if (!pickerResult.cancelled) { this.handleUploadPhoto(pickerResult) } }
Extension, this is an example converst file from base64 to binary
function convertToByteArray(input) { var binary_string = atob(input); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes } function atob(input) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; let str = input.replace(/=+$/, '); let output = '; if (str.length % 4 === 1) { throw new Error("'atob' failed: The string to be decoded is not correctly encoded."); } let bc = 0, bs = 0, buffer, i = 0 for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 ) { buffer = chars.indexOf(buffer); } return output; }
If server requires type of file is binary, you can use this to convert image file and upload ( this code use apisauce and sagas)
const responsePhoto = yield call(() => API.post( url, convertToByteArray(action.pickerResult.base64), ))
After uploading, you should save image url into reducer and update on UI. If you don't know how to work with sagas or apisauce, you can leave message, I can help you work with them