How to upload image from library or camera with CRNA
Bài đăng này đã không được cập nhật trong 5 năm
CRNA (create react native app ) works with expo, so I will demo an example help you access the library from your device or access a camera, take a photo and upload to a server. In this post, I only demo front end with react native.
To 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 this
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.width / 2 - 301, // get center image
y: pickerResult.height / 2 - 301,
width: 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
All rights reserved