Firebase: Vue.js : Not able to connect storage with database - javascript

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})
})
...

Related

Vue Firebase cannot not fetch image url after uploading image

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 });
})
...

How to solve "File name too long" while uploading local Image to Firestore and Firebase Storage in React Native?

I'm trying to upload local images to Cloud Firestore and Firebase storage.
The PACKAGES I'm using are
react-native-image-picker to choose an image from local
rn-fetch-blob to transfer files as blob to Firebase storage
Here's the 2 functions I'm using:
export const uploadPost = async (postImageUri) => {
return new Promise(async(res, rej) => {
const fs = RNFetchBlob.fs;
fs.readFile(postImageUri,'hello','base64')
.then(async (data) => {
console.log('data from RNFetchBlob', data);
const storageRef = storage().ref(`posts/images`).child(`${data}`);
try {
storageRef.putFile(data,{contentType: 'image/jpeg'})
.on(
storage.TaskEvent.STATE_CHANGED,
snapshot => {
console.log('snapshot', snapshot.state);
console.log('progress', (snapshot.bytesTransferred)/(snapshot.totalBytes)*100);
if(snapshot.state === storage.TaskState.SUCCESS){
console.log('SUCCESS')
}
},
error => {
console.log('Image upload error', error);
rej(error)
},
() => {
storageRef.getDownloadURL()
.then((downLoadUri) => {
console.log('File available at: ', downLoadUri);
// addPostInfo
res(downLoadUri)
})
}
)
}catch{err => console.log(err) }
})
} )
}
export const addPostInfo = async (post) => {
console.log('post.postImageUri in addPostInfo', post.postImageUri.slice(10))
const remoteUri = await uploadPost(post.postImageUri);
return new Promise((res, rej) => {
firestore()
.collection('posts')
.add({
id: post.id,
createdAt: post.date,
description: post.description,
image: remoteUri,
location: post.checkin_location
})
.then(ref => {
console.log('Finish adding in addPostInfo', ref)
res(ref)
})
.catch(err => rej(err))
})
}
And in the main screen, I directly send the image's path to the addPostInfo:
const _onSharingPost = () => {
const postCreated = {
id: 'alkdgjhfa;oiughaoghus',
postImageUri: postImageUri,
date: _getCurrentDate(),
description: postDescription,
checkin_location: checkInLocation
}
postActions.addPostInfo(postCreated);
}
The path is like this:
content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F58/ORIGINAL/NONE/image%2Fjpeg/950379202
ERROR
...base64 string --> File name too long
It got down to the SUCCESS part of the upLoadPost function but then still got error
I HAVE TRIED:
Change the path --> cut off the content://
Use XMLHttpRequest to send the blob to the upLoadPost to send that to the storage
As far as I know, the problem must be the base64 string converted from the image path. I know we need to change that to blob or something, but I don't know how. I can't find where this can be specified in rn-fetch-blob docs
PLEASE HELP ME

Firebase upload function works differently everytime

I have a form to upload a new item, that has a few fields and an image.
The way I've built the function is that it first sets the new document in Firestore, then it uploads the image, and then it resets the form.
The problem is that it doesn't always work. Sometimes the image gets uploaded and sometimes it isn't even if the form was reset (the reset is conditioned with the image upload).
It's not consistent so I can't figure out what exactly is happening.
This is the upload function:
export const newItem = (values, image, setValues) => () => {
const newDoc = db.collection("items").doc();
newDoc.set({ ...values, id: newDoc.id }).then(() => {
storageRef
.child(`images/items/${newDoc.id}`)
.put(image)
.then(result => {
console.log(result);
setValues({});
});
});
};
I call it is as follows:
newItem({ ...values, is_public }, imageObj, setValues);
Then I have this cloud function that addes the url for the newly uploaded file to the new document (but I don't think the issue is there, because when I say the image wasn't uploaded, then I mean I don't even see it in storage):
exports.writeFileToDatabase = functions.storage.object().onFinalize(object => {
const bucket = defaultStorage.bucket();
const path = object.name as string;
const file = bucket.file(path);
return file
.getSignedUrl({
action: "read",
expires: "03-17-2025"
})
.then(results => {
const url = results[0];
const silcedPath = path.split("/", 3);
switch (silcedPath[1]) {
case "user-avatars":
return db
.collection("users")
.doc(silcedPath[2])
.set({ avatar: url }, { merge: true });
case "items":
return db
.collection("items")
.doc(silcedPath[2])
.set({ image: url }, { merge: true });
default:
return null;
}
});
});
EDIT:
this is how I choose the file:
<input
id="image"
className="new-item__upload"
type="file"
onChange={handleImageChange}
/>
Then this is handleImageChange:
const handleImageChange = e => {
if (e.target.files[0]) {
const image = e.target.files[0];
setSelectedImage(URL.createObjectURL(image));
setImageObj(image); // This is what end up being given to the function to upload
}
};
You need to correctly chain the promises returned by the Firebase asynchronous operations (set() and put()) as follows:
export const newItem = (values, image, setValues) => () => {
const newDoc = db.collection("items").doc();
newDoc.set({ ...values, id: newDoc.id })
.then(() => {
return storageRef //Here return the Promise returned by the put() method
.child(`images/items/${newDoc.id}`)
.put(image);
})
.then(snapshot => {
console.log(snapshot);
setValues({});
})
.catch(e => {
console.error(e.message);
//You should throw an error here, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling
});
};
It is also recommended to add a catch() method call at the end of your Promises chain, in order to get more details in case of error.

Upload data to firebase storage and Firebase database from array in react native

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
});

access firebase data id within push

complete noob here.
Trying to retrieve the firebase unique id from the first data push to use in the second so that I can reference the data between the two data sets. I used stackoverflow answers to retrieve the key, but my code didnt work.
(If you have a better way of referencing the two items other than utilizing firebase unique id, Im all for it!) thanks!!
export const GROUP_CREATE = 'group_create';
export const groupCreate = ({ name, course, members }) => {
const { currentUser } = firebase.auth();
return (dispatch) => {
var pushedRef = firebase.database().ref(`/groups`).push({ name })
var dataId = pushedRef.key
.then(
firebase.database().ref('/groups')
.push({ name, dataId, course, members }))
.then(() => {
dispatch({ type: GROUP_CREATE });
Actions.groupMain({ type: 'reset' });
});
};
};
I figured it out!
export const GROUP_CREATE = 'group_create';
export const groupCreate = ({ name, course, members }) => {
const { currentUser } = firebase.auth();
var myRef = firebase.database().ref('/groups').push();
var groupId = myRef.key;
return (dispatch) => {
myRef.push({ name, course, members })
.then(
firebase.database().ref(`/users/${currentUser.uid}/groups`)
.push({ name, groupId }))
.then(() => {
dispatch({ type: GROUP_CREATE });
Actions.groupMain({ type: 'reset' });
});
};
};

Categories

Resources