
The Firebase storage service is used to store media content for all the Firebase apps (Android, iOS, and web) under a linked Firebase project. The Firebase storage service is built upon Google Cloud Storage, which allows web apps to access the content of storage directly. The data is stored in Google Cloud Storage buckets, which are nothing but a namespace to manage data and access controls. The storage service can be added with a separate NPM dependency. The images can be fetched from the device or camera using the react-native-image-picker NPM module.
This guide covers the implementation of Firebase storage and image picker module to fetch and store an image from the device to a Firebase storage bucket. Follow these other guides to complete the implementation:
The optimized codebase is available on RNFirebaseStorage repository.
Every Firebase service requires a specific NPM module to communicate with the Firebase server apps. The Firebase storage APIs can be integrated using the react-native-firebase/storage NPM module:
1# Install the storage module
2npm install @react-native-firebase/storage
3
4# setup iOS project
5cd ios && pod install --repo-update && cd ..The commands will install the Firebase storage module. Install the iOS pod dependency for the Firebase storage.
@react-native-firebase/appNPM modules is required to use most of the Firebase NPM modules.
By default, Firebase creates a storage bucket to store the media content and name the bucket using the Firebase project ID as gs://firebase-project-id.appspot.com.
Create a default storage bucket in the Firebase project:

Firebase protects the storage content from unauthorized access by using the allow read, write: if request.auth != null; rule.
1rules_version = '2';
2service firebase.storage {
3 match /b/{bucket}/o {
4 match /{allPaths=**} {
5 allow read, write;
6 }
7 }
This will enable public access to the Firebase storage bucket to every user without integrating the Firebase authentication service.
Do not use the public access rule
allow read, write; in production, it can cause data protection issues.
The images on Android or iOS devices are managed via different built-in apps (Gallery or Photos), and these images can be accessed via a specific path (URI for iOS) value. The react-native-image-picker module provides React Native-specific APIs to get the path/URI of an image on the underlying native device. Follow the below steps to install and configure the image picker:
Execute the below commands to install the image picker module and iOS pod dependency
1npm install react-native-image-picker
2cd ios && pod install && cd ..
Both Android and iOS follow the permission model to inform the user about the resource used by an app, so these permissions should be added in configurations files in the native projects.
RNFirebaseStorage/android/app/src/main/AndroidManifest.xml file to get the camera and storage access on an android device:1<uses-permission android:name="android.permission.CAMERA" />
2<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>RNFirebaseStorage/ios/RNFirebaseStorage/info.plist file to get access to photos, camera, and photo storage. Open the info.plist file with any text editor and then copy and paste all three key-string pairs from the below snippet. In Xcode, right-click on the info.plist file, choose the Opens As option, and then Source Code option:1<plist version="1.0">
2 <dict>
3 <key>NSPhotoLibraryUsageDescription</key>
4 <string>$(PRODUCT_NAME) would like access to your photo gallery</string>
5 <key>NSCameraUsageDescription</key>
6 <string>$(PRODUCT_NAME) would like to use your camera</string>
7 <key>NSPhotoLibraryAddUsageDescription</key>
8 <string>$(PRODUCT_NAME) would like to save photos to your photo gallery</string>
9 </dict>
10</plist>Alternately, this can be done in the Xcode UI by using the + button to add key and string values:

Optionally, clean the Android and iOS projects:
1#android
2cd android && ./gradlew clean && cd ..
3#iOS
4cd ios && xcodebuild clean && cd ..
The image picker can get the image either from the photo gallery or camera. The UI of the image picker dialog can also be customized using the Options object that can be passed as the first parameter to showImagePicker function call. The second parameter of showImagePicker is a callback function that will be called with a response object which contains the details about the selected image:
1chooseFile = () => {
2 this.setState({ status: '' });
3 var options = {
4 title: 'Select Image',
5 storageOptions: {
6 skipBackup: true, // do not backup to iCloud
7 path: 'images', // store camera images under Pictures/images for android and Documents/images for iOS
8 },
9 };
10 ImagePicker.showImagePicker(options, response => {
11 if (response.didCancel) {
12 console.log('User cancelled image picker', storage());
13 } else if (response.error) {
14 console.log('ImagePicker Error: ', response.error);
15 } else if (response.customButton) {
16 console.log('User tapped custom button: ', response.customButton);
17 } else {
18 let path = this.getPlatformPath(response).value;
19 }
20 });
21};
22
23/**
24 * Get platform specific value from response
25 */
26getPlatformPath({ path, uri }) {
27 return Platform.select({
28 android: { "value": path },
29 ios: { "value": uri }
30 })
31}The storageOptions object defined the path to store clicked images under the Document/Images for iOS and Pictures/images for Android. A skipBackup: true property will instruct iOS to skip the iCloud image backup for camera images.
Here's the complete code to trigger chooseFile function to fetch and display the selected image on screen:
1// App.js
2/**
3 * @author Pavneet Singh
4 */
5
6import React from "react";
7import {
8 StyleSheet,
9 View,
10 Button,
11 Image,
12 ActivityIndicator,
13 Platform,
14 SafeAreaView,
15 Text,
16} from "react-native";
17import storage from '@react-native-firebase/storage';
18import ImagePicker from 'react-native-image-picker';
19export default class App extends React.Component {
20
21 state = {
22 // placeholder image
23 imagePath: require("./img/default.jpg")
24 }
25
26 chooseFile = () => {
27 var options = {
28 title: 'Select Image',
29 storageOptions: {
30 skipBackup: true, // do not backup to iCloud
31 path: 'images', // store camera images under Pictures/images for android and Documents/images for iOS
32 },
33 };
34 ImagePicker.showImagePicker(options, response => {
35 if (response.didCancel) {
36 console.log('User cancelled image picker', storage());
37 } else if (response.error) {
38 console.log('ImagePicker Error: ', response.error);
39 } else if (response.customButton) {
40 console.log('User tapped custom button: ', response.customButton);
41 } else {
42 let path = this.getPlatformPath(response).value;
43 let fileName = this.getFileName(response.fileName, path);
44 this.setState({ imagePath: path });
45 }
46 });
47 };
48
49 /**
50 * Get the file name and handle the invalid null case
51 */
52 getFileName(name, path) {
53 if (name != null) { return name; }
54
55 if (Platform.OS === "ios") {
56 path = "~" + path.substring(path.indexOf("/Documents"));
57 }
58 return path.split("/").pop();
59 }
60
61 /**
62 * Get platform specific value from response
63 */
64 getPlatformPath({ path, uri }) {
65 return Platform.select({
66 android: { "value": path },
67 ios: { "value": uri }
68 })
69 }
70
71 /**
72 * Get platform-specific Uri with the required format
73 */
74 getPlatformURI(imagePath) {
75 let imgSource = imagePath;
76 if (isNaN(imagePath)) {
77 imgSource = { uri: this.state.imagePath };
78 if (Platform.OS == 'android') {
79 imgSource.uri = "file:///" + imgSource.uri;
80 }
81 }
82 return imgSource
83 }
84
85 render() {
86 let { imagePath } = this.state;
87 let imgSource = this.getPlatformURI(imagePath)
88 return (
89 <SafeAreaView style={styles.container}>
90 <View style={styles.imgContainer}>
91 <Image style={styles.uploadImage} source={imgSource} />
92 <View style={styles.eightyWidthStyle} >
93 <Button title={'Upload Image'} onPress={this.chooseFile}></Button>
94 </View>
95 </View>
96 </SafeAreaView>
97 )
98 }
99}
100
101const styles = StyleSheet.create({
102 container: {
103 flex: 1,
104 width: '100%',
105 height: '100%',
106 backgroundColor: '#e6e6fa',
107 },
108 imgContainer: {
109 alignItems: 'center',
110 justifyContent: 'center',
111 position: 'absolute',
112 width: '100%',
113 height: '100%'
114 },
115 eightyWidthStyle: {
116 width: '80%',
117 margin: 2,
118 },
119 uploadImage: {
120 width: '80%',
121 height: 300,
122 },
123});A successful image selection will trigger the else case in chooseFile method and provide the image details via the response object. The getPlatformPath function will return a platform-specific path/URI value that is being stored in the state object to update the image on the screen.
Firebase services like storage, database, and Firestore can use the Firebase rules to validate the data and users. Firebase storage is built upon the Google Cloud Storage service so it can store petabytes of data.
The image-picker module offers a quick way to fetch images from the devices. It also supports functions like launchCamera and launchImageLibrary to use a specific image source.
Follow this guide to learn about uploading a selected image to the Firebase storage bucket. Happy coding!