React Native – File System Access
File Picker
React native by default dose not support File Picker functionality but using the react-native-document-picker NPM library we can implement file picker in both Android and iOS devices. One more thing Android emulator does support the File picker but in iOS devices iPhone did not support file picker. If you want to test file picker functionality in iOS devices then you have to use real devices for testing purpose. Using the document file picker we can pick all the type of files from our mobile phones. We can also select separate files like images files, plain text files, audio files, pdf files and all the files present in mobile system. So in this tutorial we would Create File Picker in React Native Android Example Tutorial.
So for using the File Picker in our application we have to first install the dependencies.
npm install react-native-document-picker --save
//After that we have to link this
react-native link react-native-document-picker
We are going to access external storage so we need to add some permission to the AndroidManifest.xml file.
So we are going to add the following permissions in the AndroidManifest.xml.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Permission Purpose
READ_EXTERNAL_STORAGE To Read the content of the SD card
App.js Code
import React from 'react';
import {
StyleSheet,
Text,
View,
Button,
TouchableOpacity,
ScrollView,
Image,
} from 'react-native';
import DocumentPicker from 'react-native-document-picker';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
singleFile: '',
multipleFile: [],
};
}
async selectOneFile() {
//Opening Document Picker for selection of one file
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
//There can me more options as well
// DocumentPicker.types.allFiles
// DocumentPicker.types.images
// DocumentPicker.types.plainText
// DocumentPicker.types.audio
// DocumentPicker.types.pdf
});
//Printing the log realted to the file
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res.uri);
console.log('Type : ' + res.type);
console.log('File Name : ' + res.name);
console.log('File Size : ' + res.size);
//Setting the state to show single file attributes
this.setState({ singleFile: res });
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
}
async selectMultipleFile() {
//Opening Document Picker for selection of multiple file
try {
const results = await DocumentPicker.pickMultiple({
type: [DocumentPicker.types.images],
});
for (const res of results) {
console.log('res : ' + JSON.stringify(res));
console.log('URI : ' + res.uri);
console.log('Type : ' + res.type);
console.log('File Name : ' + res.name);
console.log('File Size : ' + res.size);
}
//Setting the state to show multiple file attributes
this.setState({ multipleFile: results });
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from multiple doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
}
render() {
return (
<View style={styles.containerStyle}>
<TouchableOpacity
activeOpacity={0.5}
style={styles.buttonStyle}
onPress={this.selectOneFile.bind(this)}>
{/*Single file selection button*/}
<Text style={{ marginRight: 10, fontSize: 19 }}>
Click here to pick one file
</Text>
<Image
source={{
uri: 'https://img.icons8.com/offices/40/000000/attach.png',
}}
style={styles.imageIconStyle}
/>
</TouchableOpacity>
{/*Showing the data of selected Single file*/}
<Text style={styles.textStyle}>
File Name:{' '}
{this.state.singleFile.name ? this.state.singleFile.name : ''}
{'\n'}
Type: {this.state.singleFile.type ? this.state.singleFile.type : ''}
{'\n'}
File Size:{' '}
{this.state.singleFile.size ? this.state.singleFile.size : ''}
{'\n'}
URI: {this.state.singleFile.uri ? this.state.singleFile.uri : ''}
{'\n'}
</Text>
<View style={{ backgroundColor: 'grey', height: 2, margin: 10 }} />
{/*To multiple single file attribute*/}
<TouchableOpacity
activeOpacity={0.5}
style={styles.buttonStyle}
onPress={this.selectMultipleFile.bind(this)}>
{/*Multiple files selection button*/}
<Text style={{ marginRight: 10, fontSize: 19 }}>
Click here to pick multiple files
</Text>
<Image
source={{
uri: 'https://img.icons8.com/offices/40/000000/attach.png',
}}
style={styles.imageIconStyle}
/>
</TouchableOpacity>
<ScrollView>
{/*Showing the data of selected Multiple files*/}
{this.state.multipleFile.map((item, key) => (
<View key={key}>
<Text style={styles.textStyle}>
File Name: {item.name ? item.name : ''}
{'\n'}
Type: {item.type ? item.type : ''}
{'\n'}
File Size: {item.size ? item.size : ''}
{'\n'}
URI: {item.uri ? item.uri : ''}
{'\n'}
</Text>
</View>
))}
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
backgroundColor: '#fff',
padding: 16,
},
textStyle: {
backgroundColor: '#fff',
fontSize: 15,
marginTop: 16,
color: 'black',
},
buttonStyle: {
alignItems: 'center',
flexDirection: 'row',
backgroundColor: '#DDDDDD',
padding: 5,
},
imageIconStyle: {
height: 20,
width: 20,
resizeMode: 'stretch',
},
});
File Viewer
This example will cover how to pick any file from the file system and view that file in a native File Viewer. Here native file viewer means we are not going to view the file in our application instead we will pick the file from file picker and will pass the file URL to FileViewer component provided by react-native-file-viewer, this component will trigger the native iOS/Android file viewer to open the file.
For example,
You have selected an Image then it will open it in an image viewer or if you have multiple options to view the image then you will be asked to select an application to view the image
If you have selected any pdf then it will open any pdf reader from your device
On selection of any video, it will trigger a video player of your device to play the video.
Now we need to install the dependencies which we require for this project. Open the terminal and jump into your project
For the file picker install react-native-document-picker using the following command
npm install react-native-document-picker --save
Now we need to install react-native-file-viewer from which we will import FileViewer component. Please run the below command to install it
npm install react-native-file-viewer --save
Now we need to link react-native-document-picker, and react-native-file-viewer using
react-native link react-native-document-picker
react-native link react-native-file-viewer
App.js
import React from 'react';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
Platform,
} from 'react-native';
import FileViewer from 'react-native-file-viewer';
import DocumentPicker from 'react-native-document-picker';
const App = () => {
const selectOneFile = async () => {
//handler to Select File
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
if (res) {
let uri = res.uri;
if (Platform.OS === 'ios') {
//After picking the file we need to remove 'file://' from file path
//Because FileViewer will not show the file with 'file://' prefix
uri = res.uri.replace('file://', '');
}
console.log('URI : ' + uri);
FileViewer.open(uri)
.then(() => {
console.log('Success');
})
.catch(_err => {
console.log(_err);
});
}
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
return (
<View style={styles.mainBody}>
<View style={{ alignItems: 'center' }}>
<Text style={{ fontSize: 30, textAlign: 'center' }}>
Native file viewer for React Native
</Text>
<Text style={{ fontSize: 25, marginTop: 20, textAlign: 'center' }}>
Preview any type of file supported by the mobile device
</Text>
<Text
style={{
fontSize: 25,
marginTop: 20,
marginBottom: 30,
textAlign: 'center',
}}>
codehunger.in
</Text>
</View>
<TouchableOpacity
style={styles.buttonStyle}
activeOpacity={0.5}
onPress={selectOneFile}>
<Text style={styles.buttonTextStyle}>Select File to View</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
mainBody: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
buttonStyle: {
backgroundColor: '#307ecc',
borderWidth: 0,
color: '#FFFFFF',
borderColor: '#307ecc',
height: 40,
alignItems: 'center',
borderRadius: 30,
marginLeft: 35,
marginRight: 35,
marginTop: 15,
},
buttonTextStyle: {
color: '#FFFFFF',
paddingVertical: 10,
fontSize: 16,
},
});
export default App;
Upload File/Image to Server with Form Data
After selecting the images or files we are going to upload the selected items in the server. So in this section we are going to see how we can upload image or file in the server using FormData and we are writing only the frontend code. You can implement your backend code according to your language.
App.js
import React, { useState } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import DocumentPicker from 'react-native-document-picker';
const App = () => {
let [singleFile, setSingleFile] = useState(null);
let uploadImage = async () => {
//Check if any file is selected or not
if (singleFile != null) {
//If file selected then create FormData
const fileToUpload = singleFile;
const data = new FormData();
data.append('name', 'Image Upload');
data.append('file_attachment', fileToUpload);
//Please change file upload URL
let res = await fetch(
'backend url',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
);
let responseJson = await res.json();
if (responseJson.status == 1) {
alert('Upload Successful');
}
} else {
//if no file selected the show alert
alert('Please Select File first');
}
};
let selectFile = async () => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log('res : ' + JSON.stringify(res));
setSingleFile(res);
} catch (err) {
setSingleFile(null);
if (DocumentPicker.isCancel(err)) {
alert('Canceled from single doc picker');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
return (
<View style={styles.mainBody}>
<View style={{ alignItems: 'center' }}>
<Text style={{ fontSize: 30, textAlign: 'center' }}>
React Native File Upload Example
</Text>
<Text
style={{
fontSize: 25,
marginTop: 20,
marginBottom: 30,
textAlign: 'center',
}}>
codehunger.in
</Text>
</View>
{singleFile != null ? (
<Text style={styles.textStyle}>
File Name: {singleFile.name ? singleFile.name : ''}
{'\n'}
Type: {singleFile.type ? singleFile.type : ''}
{'\n'}
File Size: {singleFile.size ? singleFile.size : ''}
{'\n'}
URI: {singleFile.uri ? singleFile.uri : ''}
{'\n'}
</Text>
) : null}
<TouchableOpacity
style={styles.buttonStyle}
activeOpacity={0.5}
onPress={selectFile}>
<Text style={styles.buttonTextStyle}>Select File</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.buttonStyle}
activeOpacity={0.5}
onPress={uploadImage}>
<Text style={styles.buttonTextStyle}>Upload File</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
mainBody: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
buttonStyle: {
backgroundColor: '#307ecc',
borderWidth: 0,
color: '#FFFFFF',
borderColor: '#307ecc',
height: 40,
alignItems: 'center',
borderRadius: 30,
marginLeft: 35,
marginRight: 35,
marginTop: 15,
},
buttonTextStyle: {
color: '#FFFFFF',
paddingVertical: 10,
fontSize: 16,
},
textStyle: {
backgroundColor: '#fff',
fontSize: 15,
marginTop: 16,
marginLeft: 35,
marginRight: 35,
textAlign: 'center',
},
});
export default App;