Image Upload Component React Native Expo | by Faysal Ahmed | Cybridge Geeks | Medium
Mục lục bài viết
Image Upload Component React Native Expo
Uploading image from react native to a specific endpoint is very necessary for any react native developer. I will try to describe you how to do this things.
React Native Powerful way to develop mobile application
For this tutorial we will create a new file inside
projectRoot/src/libs/UploadImage.js.
Inside UploadImage.js we will create a basic component
add uuid using below command if not exits
npm install uuid
Create Layout of UploadImage.js and basic styling
import React,{Component} from 'react';
import {
Text,
View,
Dimensions,
ActivityIndicator,
Platform,
Alert,
Linking,
StyleSheet,
Image,
TouchableOpacity,
} from 'react-native';
import { ImagePicker, Permissions } from 'expo';
import uid from 'uuid/v4';
constructor(props){
super(props)
this.state={
endpoint:this.props.endpoint
}
defaultProps = {
onSuccess: undefined,
onFailure: undefined,
onStartUpload: undefined,
alertTitle: 'Please Allow Access',
alertMessage: [
'This applicaton needs access to your photo library to upload images.',
'\n\n',
'Please go to Settings of your device and grant permissions to Photos.',
].join(''),
alertNo: 'Not Now',
alertYes: 'Settings',
};
}
render(){
return(
<View style={style.imgwrapper}>
{this.props.callbackUrl != null ? <Image source={{uri: this.state.uploaded_photo ? this.state.uploaded_photo : this.props.callbackUrl}} style={{width: 80, height: 80,borderRadius: 40}}/> : <Image source={{uri:'
<TouchableOpacity
style={style.circleWrapper}
onPress={()=>{
this.uploadResult();
}}
>
<View />
</TouchableOpacity>
</View>
)
}
}export default class UploadImage extends Component{constructor(props){super(props)this.state={endpoint:this.props.endpointdefaultProps = {onSuccess: undefined,onFailure: undefined,onStartUpload: undefined,alertTitle: 'Please Allow Access',alertMessage: ['This applicaton needs access to your photo library to upload images.','\n\n','Please go to Settings of your device and grant permissions to Photos.',].join(''),alertNo: 'Not Now',alertYes: 'Settings',};render(){return({this.props.callbackUrl != null ? :
const style = StyleSheet.create({
imgwrapper:{
justifyContent: 'center',
alignItems: 'center',
position:'relative',
marginBottom: 80,
},
circleWrapper:{
backgroundColor:'#ECECEC',
height:22,
width:22,
borderWidth:3,
borderColor: '#ffffff',
borderRadius:11,
marginLeft:70,
marginTop: -80,
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
})
Create method for asking permission
async askPermission() {
// only if user allows permission to camera roll
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
const { onStartUpload } = this.props;
// On Android users are prompted every time,
// so no need to show additional Alert
if (status !== 'granted') {
if (Platform.OS === 'ios') this.showAlert();
return;
}
}
Show permission Alert for IOS:
If there is no permission it will open with an alert for enable the media permission & will guide to phone settings
showAlert() {
const { alertMessage, alertTitle, alertYes, alertNo } = this.props;
Alert.alert(
'Please Allow Access',
[
'This applicaton needs access to your photo library to upload images.',
'\n\n',
'Please go to Settings of your device and grant permissions to Photos.',
].join(''),
[
{ text: 'Not Now', style: 'cancel' },
{ text: 'Settings', onPress: () => Linking.openURL('app-settings:') },
],
);
}
On Press Start Upload Method:
Actually when call this method it will start upload process & call uploadImageAsync method
uploadResult = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
const { onStartUpload } = this.props;
//if status not granted it will guide to grant permission from settings
if (status !== 'granted') {
if (Platform.OS === 'ios') this.showAlert();
return;
}
Expo.ImagePicker.launchImageLibraryAsync({
mediaTypes:'Images'
}).then((result)=>{
const file = result.uri;
if(!result.cancelled){
this.setState({
loading:true
})
uploadResponse = this.uploadImageAsync(result.uri).then((reponse)=>{
console.log(reponse,'reponse');
this.setState({
loading:false,
uploaded_photo:file
})
});}
})
}
Initiate Upload image last process :
In this part of the code we have to define uri
which we get from uploadResult method. Then need to provide
1. endpoint
2. payloadKey (ex: ‘file’ or ‘field_name’)
3. If restricted api provide appropriate header information on options.headers area
async uploadImageAsync(uri) {
const uriParts = uri.split('.');
const fileType = uriParts[uriParts.length - 1];
const { headers } = this.props;
const endpoint = this.state.endpoint; // Define Endpoint Here
const payloadKey = this.state.poayloadKey; // Define PayloadKey here Ex. 'file'
const method = 'POST';
const formData = new FormData();
formData.append(payloadKey, {
uri,
name: uid(),
type: `image/${fileType}`,
});
const options = {
method,
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': this.state.token, // If restricted provide appropriate token here otherwise ignore or remove this line
},
};
return fetch(endpoint, options);
}
So the final UploadImage.js is look like:
import {
Text,
View,
Dimensions,
ActivityIndicator,
Platform,
Alert,
Linking,
StyleSheet,
Image,
TouchableOpacity,
} from 'react-native';
import { ImagePicker, Permissions } from 'expo';
import uid from 'uuid/v4';
export default class UploadImage extends Component{
constructor(props){
super(props)
this.askPermission = this.askPermission.bind(this);
this.showAlert = this.showAlert.bind(this);
this.state={
endpoint:this.props.endpoint?this.props.endpoint:null,
payloadKey:this.props.payloadKey? this.props.payloadKey:null,
token:this.props.token?this.props.token:null,
callbackUrl:this.props.callbackUrl?this.props.callbackUrl:null,
loading:false
}
defaultProps = {
onSuccess: undefined,
onFailure: undefined,
onStartUpload: undefined,
alertTitle: 'Please Allow Access',
alertMessage: [
'This applicaton needs access to your photo library to upload images.',
'\n\n',
'Please go to Settings of your device and grant permissions to Photos.',
].join(''),
alertNo: 'Not Now',
alertYes: 'Settings',
};
}
async askPermission() {
// only if user allows permission to camera roll
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
const { onStartUpload } = this.props;
// On Android users are prompted every time,
// so no need to show additional Alert
if (status !== 'granted') {
if (Platform.OS === 'ios') this.showAlert();
return;
}
}
showAlert() {
const { alertMessage, alertTitle, alertYes, alertNo } = this.props;
Alert.alert(
'Please Allow Access',
[
'This applicaton needs access to your photo library to upload images.',
'\n\n',
'Please go to Settings of your device and grant permissions to Photos.',
].join(''),
[
{ text: 'Not Now', style: 'cancel' },
{ text: 'Settings', onPress: () => Linking.openURL('app-settings:') },
],
);
}
uploadResult = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
const { onStartUpload } = this.props;
console.log(status,'status');
if (status !== 'granted') {
if (Platform.OS === 'ios') this.showAlert();
return;
}
Expo.ImagePicker.launchImageLibraryAsync({
mediaTypes:'Images'
}).then((result)=>{
console.log(result,'result');
const file = result.uri;
if(!result.cancelled){
this.setState({
loading:true
})
uploadResponse = this.uploadImageAsync(result.uri).then((reponse)=>{
console.log(reponse,'reponse');
this.setState({
loading:false,
uploaded_photo:file
})
});
}
})
}
async uploadImageAsync(uri) {
const uriParts = uri.split('.');
const fileType = uriParts[uriParts.length - 1];
const { headers } = this.props;
const endpoint = this.state.endpoint; // Define Endpoint Here
const payloadKey = this.state.poayloadKey; // Define PayloadKey here Ex. 'file'
const method = 'POST';
const formData = new FormData();
formData.append(payloadKey, {
uri,
name: uid(),
type: `image/${fileType}`,
});
const options = {
method,
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': this.state.token, // If restricted provide appropriate token here otherwise ignore or remove this line
},
};
return fetch(endpoint, options);
}
render(){
if(this.state.loading){
return(
<View style={[style.container]}>
<ActivityIndicator size="large" color="#FF8241" />
</View>
)
}
return(
<View style={style.imgwrapper}>
{this.props.callbackUrl != null ? <Image source={{uri: this.state.uploaded_photo ? this.state.uploaded_photo : this.props.callbackUrl}} style={{width: 80, height: 80,borderRadius: 40}}/> : <Image source={{uri:'
<TouchableOpacity
style={style.circleWrapper}
onPress={()=>{
this.uploadResult();
}}
>
<View />
</TouchableOpacity>
</View>
)
}
}
const style = StyleSheet.create({
imgwrapper:{
justifyContent: 'center',
alignItems: 'center',
position:'relative',
marginBottom: 80,
},
circleWrapper:{
backgroundColor:'#ECECEC',
height:22,
width:22,
borderWidth:3,
borderColor: '#ffffff',
borderRadius:11,
marginLeft:70,
marginTop: -80,
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
})import React,{Component} from 'react';import {Text,View,Dimensions,ActivityIndicator,Platform,Alert,Linking,StyleSheet,Image,TouchableOpacity,} from 'react-native';import { ImagePicker, Permissions } from 'expo';import uid from 'uuid/v4';export default class UploadImage extends Component{constructor(props){super(props)this.askPermission = this.askPermission.bind(this);this.showAlert = this.showAlert.bind(this);this.state={endpoint:this.props.endpoint?this.props.endpoint:null,payloadKey:this.props.payloadKey? this.props.payloadKey:null,token:this.props.token?this.props.token:null,callbackUrl:this.props.callbackUrl?this.props.callbackUrl:null,loading:falsedefaultProps = {onSuccess: undefined,onFailure: undefined,onStartUpload: undefined,alertTitle: 'Please Allow Access',alertMessage: ['This applicaton needs access to your photo library to upload images.','\n\n','Please go to Settings of your device and grant permissions to Photos.',].join(''),alertNo: 'Not Now',alertYes: 'Settings',};async askPermission() {// only if user allows permission to camera rollconst { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);const { onStartUpload } = this.props;// On Android users are prompted every time,// so no need to show additional Alertif (status !== 'granted') {if (Platform.OS === 'ios') this.showAlert();return;showAlert() {const { alertMessage, alertTitle, alertYes, alertNo } = this.props;Alert.alert('Please Allow Access','This applicaton needs access to your photo library to upload images.','\n\n','Please go to Settings of your device and grant permissions to Photos.',].join(''),{ text: 'Not Now', style: 'cancel' },{ text: 'Settings', onPress: () => Linking.openURL('app-settings:') },],);uploadResult = async () => {const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);const { onStartUpload } = this.props;console.log(status,'status');if (status !== 'granted') {if (Platform.OS === 'ios') this.showAlert();return;Expo.ImagePicker.launchImageLibraryAsync({mediaTypes:'Images'}).then((result)=>{console.log(result,'result');const file = result.uri;if(!result.cancelled){this.setState({loading:true})uploadResponse = this.uploadImageAsync(result.uri).then((reponse)=>{console.log(reponse,'reponse');this.setState({loading:false,uploaded_photo:file})});})async uploadImageAsync(uri) {const uriParts = uri.split('.');const fileType = uriParts[uriParts.length - 1];const { headers } = this.props;const endpoint = this.state.endpoint; // Define Endpoint Hereconst payloadKey = this.state.poayloadKey; // Define PayloadKey here Ex. 'file'const method = 'POST';const formData = new FormData();formData.append(payloadKey, {uri,name: uid(),type: `image/${fileType}`,});const options = {method,body: formData,headers: {Accept: 'application/json','Content-Type': 'multipart/form-data','Authorization': this.state.token, // If restricted provide appropriate token here otherwise ignore or remove this line},};return fetch(endpoint, options);render(){if(this.state.loading){return(return({this.props.callbackUrl != null ? : const style = StyleSheet.create({imgwrapper:{justifyContent: 'center',alignItems: 'center',position:'relative',marginBottom: 80,},circleWrapper:{backgroundColor:'#ECECEC',height:22,width:22,borderWidth:3,borderColor: '#ffffff',borderRadius:11,marginLeft:70,marginTop: -80,},container: {flex: 1,backgroundColor: '#fff',alignItems: 'center',justifyContent: 'center',},})
Now you can add it to your desired component with four props
import UploadImage from 'src/libs/UploadImage';
Props list is given below-
payloadKey (Required) // field name
endpoint (Required) // Endpoint Url
callbackUrl (Optional) // Callback image url
token (Optional) // Restricted Api token
payloadKey='file' // Field name
endpoint='
callbackUrl={FetchedProfileImage} // CallBack Image url
token={this.state.tokenName} // Api Token if no restriction ignore it
/>https://www.api.com/upload' // url is fake replace with your owncallbackUrl={FetchedProfileImage} // CallBack Image urltoken={this.state.tokenName} // Api Token if no restriction ignore it/>
Like this you can use it to upload image on expo react native.
Hopefully it will help all you to gather basic mechanism of uploading image.