I’m trying to upload images on firebase storage using my expo app. I went through their documentation and tried to implement using the docs. but whenever I upload I don’t get any error but the image that appears on firebase is just a plain white box
Images uploaded to Firebase
Error when viewing the preview
This is my whole code
import React, { useState } from 'react';
import { Image, View, Text, Button, ActivityIndicator } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { app } from './firebaseConfig';
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import 'firebase/storage';
const App = () => {
const [image, setImage] = useState(null);
const [uploading, setUploading] = useState(false);
const pickImage = async () => {
try {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
console.log(result.assets[0].uri)
setImage(result.assets[0].uri);
}
} catch (E) {
console.log(E);
}
};
const storage = getStorage(app);
// Create the file metadata
/** @type {any} */
const metadata = {
contentType: 'image/jpeg'
};
// Upload file and metadata to the object 'images/mountains.jpg'
const storageRef = ref(storage, 'images/' + Date.now());
const uploadTask = uploadBytesResumable(storageRef, image, metadata);
console.log(storageRef)
// Listen for state changes, errors, and completion of the upload.
uploadTask.on('state_changed',
(snapshot) => {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error) => {
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
switch (error.code) {
case 'storage/unauthorized':
// User doesn't have permission to access the object
break;
case 'storage/canceled':
// User canceled the upload
break;
// ...
case 'storage/unknown':
// Unknown error occurred, inspect error.serverResponse
break;
}
},
() => {
// Upload completed successfully, now we can get the download URL
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
});
}
);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Pick an image from camera roll" onPress={pickImage} />
{image && (
<>
<Image source={{ uri: image }} style={{ width: 200, height: 200 }} />
</>
)}
{uploading && <ActivityIndicator />}
</View>
);
};
export default App;
2
Answers
The URL path
result.assets[0].uri
returned byexpo-image-picker
is a reference to image data but not contains actual image data.As firebase expects to upload binary data, the app requires to fetch image binary data first.
I wrote an in-depth article on this subject – https://dev.to/emmbyiringiro/upload-image-with-expo-and-firebase-cloud-storage-3481
Create a new file filename.js and paste this code. Import pickImage function to pick image from gallery and uploadImage to upload the image you picked. uploadImage has to parameters -> uri and path. uri is the value returned from pickImage function and path is the storage path where you want to store the image, eg:
images/{Date.now()}_img.png
.