I have this form that creates an anime instance and saves it on Firebase but images are not being saved and everything else yes
<form @submit.prevent="onSubmit">
<label>Anime Name:</label>
<input v-model="form.name" required /><br />
<label>Rating:</label>
<input v-model="form.rating" required /><br />
<label>Image:</label>
<input type="file" v-model="form.image"/>
<button type="submit">Create Anime</button>
</form>
this is my setup on of same Vue Component:
const form = reactive({
name: "",
rating: "",
image: ""
});
const onSubmit = async () => {
await createAnime ({...form});
}
and this is the createAnime method which I import from my firebase.js file:
const firebaseApp = firebase.initializeApp(config)
const db = firebaseApp.firestore()
const animeCollection = db.collection('animes')
export const createAnime = anime => {
return animeCollection.add(anime)
}
What can I do to save images?
CodePudding user response:
As tjg92 explains in his comment, you cannot pass a file in the object used to write to Firestore (i.e. the object passed to the add()
method).
As explained in the doc , "Cloud Firestore lets you write a variety of data types inside a document, including strings, booleans, numbers, dates, null, and nested arrays and objects" but not a file object.
What we usually do in your case is:
- Save the file in Cloud Storage with the
uploadBytes()
method. - Save the non-file data (
name
andrating
in your case) in Firestore. - Link the two elements, either by (re)naming the file with the Firestore document ID, or saving the file path in the Firestore document, or adding the Firestore document ID as a metadata of the file. It's up to you to choose the most appropriate approach, depending on your use case.
CodePudding user response:
I limit myself only to solving the problem/question based on the interpretation of the code provided
What you need to do is use firebase Storage, where your file will reside, and given your need to have it available in the firestore collection ('animes'), then you can save the URL of the file in the image field. Steps:
Step 1: Convert your image file to BLOB = fileBlob
Step 2: Create a root reference (Firebase Storage/Cloud Storage) & Firestore.
const storageRef = firebaseApp.storage().ref();
let uploadTask = storageRef.child(`/animes/`).put(fileBlob);
const db = firebaseApp.firestore();
const animeCollection = db.collection('animes');
Step 3: Listen for state changes, errors, and completion of the upload. And update collection 'animes' with imageURL/downloadURL.
uploadTask.on('state_changed',
(snapshot) => {
// Observe state change events such as progress, pause, and resume
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' progress '% done');
switch (snapshot.state) {
case firebase.storage.TaskState.PAUSED: // or 'paused'
console.log('Upload is paused');
break;
case firebase.storage.TaskState.RUNNING: // or 'running'
console.log('Upload is running');
break;
}
},
(error) => {
// Handle unsuccessful uploads
},
() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
console.log('File available at', downloadURL);
// Now update the collection, assuming it was already registered, but you can also register directly here with .set() or .add()
return animeCollection.doc(docID_or_docUID).update({ image: downloadURL })
});
}
);
I leave the official doc--> https://firebase.google.com/docs/storage/web/upload-files?authuser=0#web-version-8
I hope it will be useful