createMeetup({ commit, getters }, payload) {
const meetup = {
title: payload.title,
location: payload.location,
desciption: payload.desciption,
date: payload.date.toISOString(),
creatorId: getters.user.id
};
let imageUrl;
let key;
firebaseApp
.database()
.ref("meetups")
.push(meetup)
.then(data => {
key = data.key;
return key;
})
.then(key => {
const filename = payload.image.name;
const ext = filename.slice(filename.lastIndexOf("."));
return firebaseApp
.storage()
.ref("meetups/" + key + "." + ext)
.put(payload.image);
})
.then(fileData => {
// TODO: Image ref not found
imageUrl = fileData.ref.getDownloadURL();
return firebaseApp
.database()
.ref("meetups")
.child(key)
.update({ imageUrl: imageUrl });
})
.then(() => {
commit("createMeetup", {
...meetup,
imageUrl: imageUrl,
id: key
});
})
.catch(err => {
console.log(err);
});
},
After the TODO part of giving an error. I think it provides promise but cannot figure out how to deal with it. The error is Invalid prop: type check failed for prop "src". Expected String, Object, got Promise
getDownloadURL() returns a promise, not a string. You need to use the promise to get the URL asynchronously, as shown in the documentation.
...
.then(fileData => {
return fileData.ref.getDownloadURL();
})
.then(imageUrl => {
return firebaseApp
.database()
.ref("meetups")
.child(key)
.update({ imageUrl: imageUrl });
})
...
Related
I have several folders in firebase storage that contain images (each folder corresponds to an entity).https://i.stack.imgur.com/s9ZpX.png
When I want to download the url of each entity, what firebase does is bring me all the images that it has in the storage even if it does the forEach to each entity.
useEffect(() => {
setLoading(true);
Promise.all([getRooms(), getLocation()])
.then((values) => {
const roomsSnapshot = values[0];
const rooms = [];
const pUrl = [];
roomsSnapshot.forEach((doc) => {
const splitAddress = doc.data().address.split(", ");
formatedAddress.current = splitAddress[1] + " " + splitAddress[0];
//Download from storage//
storage
.ref(`${doc.data().roomPhotoId}/`)
.list()
.then(function (result) {
result.items.forEach((imageRef) => {
imageRef.getDownloadURL().then((url) => {
console.log(url)
roomItems.push(url)
});
});
setRoomsImagesCounter(roomsImagesCounter + 1);
// no photos scenario
if (result.items.length === 0) {
setLoading(false);
}
});
//pushing entity data//
rooms.push({
...doc.data(),
id: doc.id,
photosURL: roomItems,
shortAddress: formatedAddress.current,
coordsAddress: coords.current,
});
});
console.log(rooms);
setRooms(rooms);
// getPhotos(rooms);
setLoading(false);
})
.catch((err) => {
console.log("Error getting getting rooms or user role", err);
});
// eslint-disable-next-line react-hooks/exhaustive-deps }, []);
I don't know why firebase brings me all the images instead of bringing me the images separately for each entity.
I hope you have understood and I await your answers or any questions you have.
Thanks!
UPDATE
This is the console.log(rooms) https://i.stack.imgur.com/rQkoB.png
Can you try to create the storage ref like this:
// Create a reference under which you want to list
var listRef = storage.ref().child(`${doc.data().roomPhotoId}/`);
// Find all the prefixes and items.
listRef.listAll()
.then((res) => {
res.prefixes.forEach((folderRef) => {
// All the prefixes under listRef.
// You may call listAll() recursively on them.
});
res.items.forEach((itemRef) => {
// All the items under listRef.
});
}).catch((error) => {
// Uh-oh, an error occurred!
});
Make sure to use listAll.
Be aware that:
root.child('images').listAll() will return /images/uid as a prefix.
root.child('images/uid').listAll() will return the file as an item.
You can find more about it here.
Your code with grouping the downloadURLS:
useEffect(() => {
setLoading(true);
Promise.all([getRooms(), getLocation()])
.then((values) => {
const roomsSnapshot = values[0];
const rooms = [];
const pUrl = [];
roomsSnapshot.forEach((doc) => {
const splitAddress = doc.data().address.split(", ");
formatedAddress.current = splitAddress[1] + " " + splitAddress[0];
//Download from storage//
rooms[`${doc.data().roomPhotoId}`]=[]
storage
.ref(`${doc.data().roomPhotoId}/`)
.list()
.then(function (result) {
result.items.forEach((imageRef) => {
imageRef.getDownloadURL().then((url) => {
console.log(url)
roomItems.push(url)
});
});
setRoomsImagesCounter(roomsImagesCounter + 1);
// no photos scenario
if (result.items.length === 0) {
setLoading(false);
}
});
//pushing entity data//
rooms[`${doc.data().roomPhotoId}`].push({
...doc.data(),
id: doc.id,
photosURL: roomItems,
shortAddress: formatedAddress.current,
coordsAddress: coords.current,
});
});
console.log(rooms);
setRooms(rooms);
// getPhotos(rooms);
setLoading(false);
})
.catch((err) => {
console.log("Error getting getting rooms or user role", err);
});
// eslint-disable-next-line react-hooks/exhaustive-deps }, []);
I am working on my first Vue-Projeect with firebase.
I would like to create locations with particular images and other data.
I am working with a tutorial which is unfortunately a bit outdated. Currently I am struggeling with the connection of firebase storage with firebase database.
I am not able to push the downloadable imageUrl in the firebase storage and store it in the database.
Can you guys help me out here?
Thank you
createLocation( {commit, getters}, payload) {
const location = {
title: payload.title,
location: payload.location,
description: payload.description,
creationDate: payload.creationDate,
rating: payload.rating,
coordinates: payload.coordinates,
filters: payload.filters,
creatorId: getters.user.id
}
let imageUrl
let key
firebase.database().ref('locations').push(location)
.then((data) => {
key = data.key
return key
})
.then(key => {
const filename = payload.image.name
const ext = filename.slice(filename.lastIndexOf('.'))
console.log(payload.image)
return firebase.storage().ref('locations/' + key + ext).put(payload.image)
})
.then(fileData => {
imageUrl = fileData.metadata.getDownloadURL
return firebase.database().ref('meetups').child(key).update({imageUrl: imageUrl})
})
.then(() => {
commit('createLocation', {
...location,
imageUrl:imageUrl,
id: key
})
})
.catch((error) => {
console.log(error)
})
},
If you look at the reference documentation for metadata.downloadURL it says:
deprecated
Use Reference.getDownloadURL instead. This property will be removed in a future release.
Determining the download URL for a file now requires another roundtrip to the server, so you'll need another then block for that:
firebase.database().ref('locations').push(location)
...
.then(key => {
const filename = payload.image.name
const ext = filename.slice(filename.lastIndexOf('.'))
console.log(payload.image)
return firebase.storage().ref('locations/' + key + ext).put(payload.image)
})
.then(fileData => {
return fileData.ref.getDownloadURL();
})
.then(imageUrl => {
return firebase.database().ref('meetups').child(key).update({imageUrl: imageUrl})
})
...
I tried to connect my react native app to the firebase as following. After executing this 'add post' function neither generating an error message or storing the data in firebase. But the photo uploading function is working as charm. Also I can authenticate and create new users. I would like to know the reason for this issue?
Current firebase dependency "firebase": "^7.14.2". I also inspected both "^6.6.2" and "^7.9.0"
Add post function
const remoteUri = await this.uploadPhotoAsync(localUri, `photos/${this.uid}/${Date.now()}`);
return new Promise((res, rej) => {
this. fireStore
.collection("posts")
.add({
text: text,
uid: this.uid,
timestamp: this.timeStamp,
image: remoteUri
})
.then(ref => {
res(ref);
})
.catch(error => {
rej(error);
});
});
};
Photo uploading function
uploadPhotoAsync=async (uri, filename) =>{
// const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
//const path=`file://photos/${this.uid}/${Date.now()}.jpg`
//const path='/storage/emulated/0/Download/20200123_104742.jpg'
return new Promise(async (res, rej) => {
const response = await fetch(uri);
const file = await response.blob();
let upload = firebase
.storage()
.ref(filename)
.put(file);
upload.on(
"state_changed",
snapshot => {},
err => {
rej(err);
},
async () => {
const url = await upload.snapshot.ref.getDownloadURL();
res(url);
}
);
});
I'm saving data in the collection in the following way:
const userEntry= {
UserId: "I want documentID here",
UserName: "",
creationDate: ""
}
const churchResult = await saveChurchData(userEntry)
const saveData = async (data: object) => {
return database.collection('users').add(data)
.then(snapshot => {
return snapshot.get().then(doc => {
doc.data()
return doc.id
}).catch(err => {
console.log('Error getting documents', err);
return null;
});
}).catch(err => {
console.log('Error getting documents', err);
return null;
});
}
Is there any way that I store "documentID" of users table in the place of UserId. How can we do that in firebase cloud functions? I'm unable to find a way to store the documentID in the documentation.
I tried following, but it is giving wrong ID not docuemntID:
const key =firebase.database().ref().push()
Since I don't see any saveChurchData() method in your code, I make the assumption that instead of doing
const churchResult = await saveChurchData(userEntry)
you wan to do
const churchResult = await saveData(userEntry)
The following would do the trick, by using the doc() method without specifying any documentPath:
const userEntry = {
UserName: "",
creationDate: ""
}
const churchResult = await saveData(userEntry)
const saveData = async (data: object) => {
try {
const docRef = database.collection('users').doc();
const docId = docRef.id;
await docRef.set({ UserId: docId, ...data });
return docId;
} catch (error) {
//...
}
}
I have an array that contains the local location of some images as shown below.
imagePath=
["file:///data/user/0/com.app.taamoutlet/cache/react-native-image-crop-picker/22536474236950.png","file:///data/user/0/com.app.taamoutlet/cache/react-native-image-crop-picker/22583225016770.png
"]
I have done uploading for a single image.
As per the code you have seen below I want to upload the images to firebase storage. I want to upload each image in the array to a single folder. And then collect the downloadable URL and each image and store that information under a single product as you see
() => {
const fs = RNFetchBlob.fs
const uid = "flyers/" + this.state.productUid;
const imageRef = firebase.storage().ref(uid).child(Math.random()+".jpg") //string "dp1.jpg"
let mime = 'image/jpg'
//------------------------------------------------
// coverting to base64
fs.readFile(this.state.imagePath, 'base64')
.then((data) => {
//console.log('data='+data);
return Blob.build(data, { type: `${mime};BASE64` })
})
.then((blob) => {
//uplaoding Image
uploadBlob = blob
return imageRef.put(blob, { contentType: mime })
})
.then(() => {
uploadBlob.close()
//getting url
return imageRef.getDownloadURL()
})
.then((url) => {
urls = url;
console.log('urls=' + urls)
//================================
try {
alert("Uploading Flyer" + this.state.title)
//-------------------------------------------
//----------Inserting Data to Database--------
usersTable = 'flyers/' + this.state.productUid,
console.log(usersTable)
firebase.database().ref(usersTable).set(
{
title: this.state.title,
description: this.state.description,
imageUrls: url,
storename: this.state.storename,
user: asyncValue,
longitude: this.state.longitude,
latitutde: this.state.latitutde
}
).then(
alert(this.state.title + " flyer sucessfully uploaded")
)
//--------------------------------------------
}
catch (error) {
this.setState({ loading: false })
this.setState({ disabled: false })
console.log(error.toString())
alert(error.toString())
}
//================================
})
}
As mentioned by Renaud, you have to use Promise.all. Please check out this example:
const promises = [fs.readFile(this.state.imagePath, 'base64'),...];
return Promise.all(promises).then((arrayOfResults) => {
const furtherPromises = [...]
return Promise.all(furtherPromises)
.then((uploadedFiles) => {
// action required
})
.catch((error) => {
// action required
});
}).catch((error) => {
// action required
});