I have on my site an page where I handled File upload, but since I upgraded Firebase (I guess it was Firebase v7/8) this particular feature is not working anymore.
To handled the file upload in firebase storage I created a custom hook, where I use the useEffect because I need it to run each time there is a new file value. I passed a parametter (file) for the file I'm trying to upload and store it in database, and that way databse contains all image's url. Then I used the datas to load images in a react components.
The error I've got:
Uncaught TypeError: projectStorage.ref is not a function
Since I'm on Firebase v9 I'm lillte bit confused about it, and don't know what to change. Thank you for your help, I really appreciate =).
useStorage.jsx (custom hook)
import {projectStorage, projectFirestore, timestamp} from '../Firebase'
import { useEffect, useState } from 'react'
function useStorage(file) {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);
useEffect(() => {
const storageRef = projectStorage.ref(file.name)
const collectionRef = projectFirestore.collection('images');
storageRef.put(file).on('state_changed', (snap) => {
let percent = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percent >> 0); // or Math.trunc()
}, (err) => {
setError(err);
}, async () =>{
const url = await storageRef.getDownloadURL();
const createdAt = timestamp();
collectionRef.add({ url, createdAt});
setUrl(url);
});
}, [file]);
return {progress, url, error};
}
export default useStorage;
There's a top level function uploadBytesResumable() to upload files while monitoring progress. Try refactoring the code as shown below:
import {projectStorage, projectFirestore, timestamp} from '../Firebase'
import { ref as storageRef, uploadBytesResumable } from "firebase/storage";
useEffect(() => {
// Creating a storage reference
const storageReference = storageRef(projectStorage, file.name);
// Creating an upload task
const uploadTask = uploadBytesResumable(storageReference, file);
// Monitoring upload progress
uploadTask.on("state_changed", (snapshot: any) => {
console.log(snapshot);
// render progress
});
}, [file])
Checkout the documentation on Upload files with Cloud Storage on Web.
Related
I am creating a site for my store and learning Vue js simultaneously. I'm stuck in the part regarding uploading a product image to firebase. I get that storageRef.put is not a function. I'm using Vue js 3 and firebase 9.
uploadImage(e) {
const file = e.target.files[0];
const storage = getStorage();
const storageRef = storageReference(storage, 'products/' + file.name);
storageRef.put(file);
}
This syntax you provide is for firebase version 8.
For version 9
import { getStorage, ref, uploadBytes } from "firebase/storage";
uploadImage(e) {
const file = e.target.files[0];
const storage = getStorage();
// Create a reference to 'mountains.jpg'
const storageRef = ref(storage, 'products/' + file.name);
uploadBytes(storageRef, file).then((snapshot) => {
console.log('Uploaded!');
});
}
For more resources.
https://firebase.google.com/docs/storage/web/upload-files#web-version-9
I am attempting to upload an mp3 to firebase storage using expo and react native. So far I've got the file into firebase storage, but it's only 9bytes large, so I'm doing something wrong. I've attempted this with blob as shown below with no success.
Here is a screenshot of the firebase storage folder showing the file uploaded but not the data of said file:
Any help is greatly appreciated, I feel like I'm missing a step to actually upload the data along with the file.
export default function SongPicker() {
const [song, setSong] = useState(null);
//Get current user through authentication
const user = auth.currentUser;
const pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({});
// Fetch the photo with it's local URI
const response = fetch(result.uri);
alert(result.uri);
console.log(result);
const file = new Blob(
[response.value], {
type: 'audio/mpeg'
});
console.log('do we see this?');
try {
//Create the file reference
const storage = getStorage();
const storageRef = ref(storage, `songs/${user.uid}/${result.name}`);
// Upload Blob file to Firebase
const snapshot = uploadBytes(storageRef, file, 'blob').then((snapshot) => {
console.log('Uploaded a song to firebase storage!');
});
setSong(result.uri);
} catch (error) {
console.log(error);
}
}
The fetch() returns a Promise so you should add an await for that as well.
const response = await fetch(result.uri);
Then try using blob() method on the Response:
const file = await response.blob()
The third param in uploadBytes should be upload metadata object but you can skip that here:
const snapshot = await uploadBytes(storageRef, file).
I have a code that will save user in the database on my profile screen, but the code worked fine on iOS, but on android it throws a "Possible unhandled Promise Rejection" with "TypeError: Symbol.asyncIterator is not defined."
Please how can solve the issue on Android so that it can save to database? I am working with React Native.
Here is the code snippet:
import {Auth, DataStore} from 'aws-amplify';
const ProfileScreen = () => {
const [name, setName] = useState('');
const [bio, setBio] = useState('');
const [gender, setGender] = useState();
const [lookingfor, setLookingfor] = useState();
const isValid = () => {
return name && bio && gender && lookingfor;
};
const save = () => {
if(!isValid()) {
console.warn('Not valid');
return;
}
const newUser = new User({
name,
bio,
gender,
lookingfor,
image: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/elon.png',
});
DataStore.save(newUser);
};
return ...
I've been doing the same project. It worked for me when I did:
npm install #azure/core-asynciterator-polyfill
Then added:
import '#azure/core-asynciterator-polyfill';
at the very top of my imports in the page I was working on.
Accoding to the documentation, since save returns a promise instead of doing the opeartion itself, add await or subscribe with then to the save function;
await DataStore.save(newUser);
or
DataStore.save(newUser).then(...);
When I get data from firebase I call a hook in the response but it makes it infinite load it. So I'm uploading a file to firebase using the filePond plugin which is working (code not shown below). Once the file is uploaded I want to load it in the component again.
So before we upload a new file I'm checking if the file already exists in the Firebase DB if so I want to set it with a useState hook but it makes it infinite load the image.
const ImageUpload = ({ firebase }) => {
const ImageUpload = ({ firebase }) => {
const [files, setFiles] = useState([])
const userId = useSelector(state => state.user.userId)
firebase
.imagesUser()
.child(userId)
.once('value', snapshot => {
if (snapshot.val() !== null) {
setFiles([
{
source: snapshot.val().downloadURL,
options: {
type: 'local'
}
}
])
}
})
return (
<div className="imageUpload">
<FilePond
files={files}
/>
</div>
)
}
I want to set the data I got from firebase with a hook inside the firebase instance but the hook keeps firing. (infinite loop)
I am using Jest to test my firebase functions. This is all in the browser, so I don't have any conflicts with firebase on the server side. When I use firebase.auth() or firebase.database() everything works fine. When I try to use firebase.storage() my tests fail.
Here is my firebase import and initialization:
import firebase from 'firebase';
import config from '../config';
export const firebaseApp = firebase.initializeApp(config.FIREBASE_CONFIG);
export const firebaseAuth = firebaseApp.auth();
export const firebaseDb = firebaseApp.database();
I have an imageUtils file that has an upload function in it:
import { firebaseApp } from './firebase';
export const uploadImage = (firebaseStoragePath, imageURL) => {
return new Promise((resolve, reject) => {
// reject if there is no imagePath provided
if (!firebaseStoragePath) reject('No image path was provided. Cannot upload the file.');
// reject if there is no imageURL provided
if (!imageURL) reject('No image url was provided. Cannot upload the file');
// create the reference
const imageRef = firebaseApp.storage().ref().child(firebaseStoragePath);
let uploadTask;
// check if this is a dataURL
if (isDataURL(imageURL)) {
// the image is a base64 image string
// create the upload task
uploadTask = imageRef.putString(imageURL);
} else {
// the image is a file
// create the upload task
uploadTask = imageRef.put(imageURL);
}
// monitor the upload process for state changes
const unsub = uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
// this is where we can check on progress
}, (error) => {
reject(error.serverResponse);
unsub();
}, () => {
// success function
resolve(uploadTask.snapshot.downloadURL);
unsub();
});
});
};
And I am trying to create a test case for that function and every time it fails with:
TypeError: _firebase3.firebaseApp.storage is not a function
When I run the app normally everything works fine and I never get errors about storage() being undefined or not a function. It is only when I try to run a test case.
I have set a console.dir(firebaseApp); line in the firebase import, and it comes back with both auth() and database() but no storage. How can I get storage to import/initialize/exist properly?
Add the following import
import "firebase/storage";
It looks like this was fixed in a recent update to the firebase javascript package:
I had the same problem. Another possible solution:
import * as firebase from "firebase";
import "firebase/app";
import "firebase/storage";