so here I want to store the array of image URL from the firebase storage in firestore. I am getting an error of undefined as my ImageUrl is undefined. please help me to solve this.The images are stored on cloud storage.
The code below shows my onSubmit function where a copy of the formdata is created.I have tried with and without '.then' and both gives me this error
const onSubmit = async (e) => {
e.preventDefault();
setLoading(true);
if (discountedPrice >= regularPrice) {
setLoading(false);
toast.error("Discounted price should be less than regular price");
}
console.log(formData);
if (images.length > 6) {
setLoading(false);
toast.error("Max of 6 images");
}
let geolocation = {};
let location;
// if (address != null) {
try {
const response = await fetch(
`https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${process.env.React_App_YOUR_GOOGLE_API_KEY}`
);
const data = await response.json();
console.log(data);
geolocation.lat = data.results[0].geometry.location.lat;
geolocation.lng = data.results[0].geometry.location.lng;
console.log(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
);
console.log(geolocation.lat);
console.log(data.status);
location =
data.status == "ZERO_RESULTS"
? undefined
: data.results[0].formatted_address;
if (location == undefined || location.includes("undefined")) {
setLoading(false);
toast.error("area does not match");
}
} catch (error) {
toast.error("area does not match");
}
//s store image to firebase
const storeImage = async (image) => {
return new Promise((resolve, reject) => {
const storage = getStorage();
const fileName = `${auth.currentUser.uid}-${image.name}-${uuidv4()}`;
const storageRef = ref(storage, "images/" + fileName);
const uploadTask = uploadBytesResumable(storageRef, image);
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
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) => {
// Handle unsuccessful uploads
reject(error);
},
() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
resolve(downloadURL);
console.log("File available at", downloadURL);
});
}
);
});
};
const imageUrls = await Promise.all(
[...images].map((image) => {
storeImage(image);
})
)
.then(() => {
console.log("urlready " + imageUrls);
uploadingListings(imageUrls);
})
.catch((error) => {
console.log(error);
setLoading(false);
toast.error("Couldn't upload image");
return;
});
const uploadingListings = async (imageUrls) => {
console.log(imageUrls);
const formDataCopy = {
...formData,
imageUrls,
geolocation,
timestamp: serverTimestamp(),
};
formDataCopy.location = address;
delete formDataCopy.address;
delete formDataCopy.images;
!formDataCopy.offer && delete formDataCopy.discountedPrice;
console.log("this is" + formDataCopy);
const docRef = await addDoc(
collection(db, "listings"),
formDataCopy
setLoading(false);
toast.success("Created a listing");
navigate(`/category/${formDataCopy.type}/${docRef.id}`);
});
};
This is how I fixed it.
Realized I wasn't returning the url to imageUrls.
And also found it not helpful using the .then with imageUrls.
const imageUrls = await Promise.all(
[...images].map((image) => {
return storeImage(image);
})
)
// .then(() => {
// console.log("urlready " + imageUrls);
// return uploadingListings(imageUrls);
// })
.catch((error) => {
console.log(error);
setLoading(false);
toast.error("Couldn't upload listing");
return;
});
console.log("urlready " + imageUrls);
const formDataCopy = {
...formData,
imageUrls,
geolocation,
timestamp: serverTimestamp(),
};
console.log(formDataCopy);
formDataCopy.location = address;
delete formDataCopy.address;
delete formDataCopy.images;
!formDataCopy.offer && delete formDataCopy.discountedPrice;
console.log("this is" + formDataCopy);
const docRef = await addDoc(
collection(db, "listings"),
formDataCopy
)
console.log(docRef);
setLoading(false);
toast.success("Created a listing");
navigate(`/category/${formDataCopy.type}/${docRef.id}`);
};
Related
after clicking add button it creates as many firestore documents as photos selected
so if I add 2 photos it will make 2 documents with these photos
imageUpload // this is a state
It looks like your post is mostly code; please add some more details.
stack overflow gives me this error so this is a dummy text
const addProduct = () => {
const collRef = collection(db, "products");
try {
const imageUrl = [];
if (imageUpload.length > 0) {
for (let i = 0; i < imageUpload.length; i++) {
const name = imageUpload[i].name + Date.now();
const storageRef = ref(storage, `img/${name}`);
const uploadTask = uploadBytesResumable(storageRef, imageUpload[i]);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 1000
) / 10;
console.log(`Upload #${i + 1} is ${progress}% done`);
},
(error) => {
console.log("error", error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then(async (url) => {
imageUrl.push({ src: url });
await addDoc(collRef, {
title,
image: imageUrl,
});
})
.catch((error) => {
console.log(error);
});
}
);
}
}else{
console.log("Photo is not selected");
}
} catch (error) {
console.log("catch", error.message);
}
};
when I submit the form to store the data on the firestore db I got this error message:
image 1
the value of images on the state is showen like this :
image 2
I find the same question posted by others but all the answers there is not working
for me
Here is my code :
const storeImage = async (image) => {
return new Promise((resolve, reject) => {
const storage = getStorage()
const fileName = `${auth.currentUser.uid}-${image.name}-${uuidv4()}`
const storageRef = ref(storage, 'images/' + fileName)
const uploadTask = uploadBytesResumable(storageRef, image)
uploadTask.on(
'state_changed',
(snapshot) => {
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
default:
break
}
},
(error) => {
reject(error)
},
() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
resolve(downloadURL)
})
}
)
})
}
const imgUrls = await Promise.all(
[...images].map((image) => storeImage(image))
).catch(() => {
setLoading(false)
toast.error('Images not uploaded')
return
})
const formDataCopy = {
...formData,
imgUrls,
geolocation,
timestamp: serverTimestamp(),
}
formDataCopy.location = address
delete formDataCopy.images
delete formDataCopy.address
!formDataCopy.offer && delete formDataCopy.discountedPrice
const docRef = await addDoc(collection(db, 'listings'), formDataCopy)
setLoading(false)
toast.success('Listing saved')
navigate(`/category/${formDataCopy.type}/${docRef.id}`)
}
I am having trouble uploading an image to the db after cropping. I am able to upload the file on Postman, but can't figure out how to do it after cropping and getting it returned as a base64.
Here is my route that works with uploading a raw file, but not the base64:
exports.uploadProfileMedia = (req, res) => {
const BusBoy = require("busboy")
const path = require("path")
const os = require("os")
const fs = require("fs")
let mediaFileName
let mediaToBeUploaded = {}
let generatedToken = uuidv4()
const busboy = new BusBoy({ headers: req.headers })
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
console.log(file, "before")
if (
mimetype !== "image/jpeg" &&
mimetype !== "image/png" &&
mimetype !== "image/heic"
) {
return res.status(400).json({ error: "Wrong file type submitted" })
}
const mediaExtension = filename.split(".")[
filename.split(".").length - 1
]
mediaFileName = `${Math.round(
Math.random() * 100000000000
).toString()}.${mediaExtension}`
const filepath = path.join(os.tmpdir(), mediaFileName)
mediaToBeUploaded = { filepath, mimetype }
file.pipe(fs.createWriteStream(filepath))
console.log(file, "after")
})
busboy.on("finish", () => {
admin
.storage()
.bucket()
.upload(mediaToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: mediaToBeUploaded.mimetype,
firebaseStorageDownloadTokens: generatedToken
}
}
})
.then(() => {
const mediaUrl = `https://firebasestorage.googleapis.com/v0/b/${firebaseConfig.storageBucket}/o/${mediaFileName}?alt=media&token=${generatedToken}`
return db
.doc(`/users/${req.user.username}`)
.update({ mediaUrl })
})
.then(() => {
return res
.status(201)
.json({ message: "Media uploaded successfully" })
})
.catch((err) => {
console.error(err)
return res.status(500).json({ error: err.code })
})
})
busboy.end(req.rawBody)
}
Here is where I pass in a base64 after cropping:
const uploadProfileMedia = (formData) => {
axios.defaults.headers.common["Authorization"] = localStorage.getItem(
"FBIdToken"
)
axios
.post("/api/user/media", formData)
.then((res) => {})
.catch((err) => console.log(err))
console.log(formData, "form")
}
Here is a snippet of the above console.log():
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDREN
Here is the function which calls the uploadProfileMedia():
const showCroppedImage = useCallback(async () => {
console.log(imageSrc, "imgsrc")
try {
const croppedImage = await getCroppedImg(
imageSrc,
croppedAreaPixels
)
setCroppedImage(croppedImage)
uploadProfileMedia(croppedImage)
console.log(croppedImage, "showcroppedImage")
} catch (e) {
console.error(e)
}
}, [imageSrc, croppedAreaPixels])
I want to create a function that is about uploading photo to Firebase Storage with react-native-fetch-blob. I'm using Redux and you can find action functions below:
My problem is that uploadImage function is not running like asynchronous. Firebase function is running before uploadImage, so application give me an error.
I think i can't make a asynchronous function. How can i fix it ?
uploadImage() function:
const uploadImage = async (imageSource, whereToUpload) => {
let imageURL = '';
const mime = 'image/jpg';
const { Blob } = RNFetchBlob.polyfill;
const { fs } = RNFetchBlob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
console.log('URI =>', imageSource.uri);
let imgUri = imageSource.uri;
let uploadBlob = null;
const imageRef = firebase.storage().ref(whereToUpload + '/' + imageSource.fileName);
const uploadUri = Platform.OS === 'ios' ? imgUri.replace('file://', '') : imgUri;
await fs.readFile(uploadUri, 'base64')
.then((data) => Blob.build(data, { type: `${mime};BASE64` }))
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
// eslint-disable-next-line no-return-assign
return imageURL = imageRef.getDownloadURL();
})
.catch((error) => {
console.log(error);
});
return imageURL;
};
and the main action is:
export const addProjectGroup = (
myUser,
groupName,
groupDescription,
groupProfilePic,
) => dispatch => {
const groupProfileFinalPic = async () => {
let finalGroupPicture = { landscape: '' };
if (_.isEmpty(groupProfilePic.src)) {
await uploadImage(groupProfilePic, 'groupPictures').then((imageURL) => {
console.log('İŞLEM TAMAM!');
console.log('SELECTED IMAGE URL =>', imageURL);
finalGroupPicture.landscape = imageURL;
});
} else {
finalGroupPicture.landscape = groupProfilePic.src.landscape;
}
return finalGroupPicture;
};
console.log("final group profile pic =>", groupProfileFinalPic());
// Önce grubu yaratalım..
// eslint-disable-next-line prefer-destructuring
const key = firebase
.database()
.ref()
.child('groups')
.push().key;
firebase
.database()
.ref('/groups/' + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid,
},
groupName,
groupDescription,
groupProfilePic: groupProfileFinalPic(),
projects: '',
})
.then(() => {
console.log('Groups oluşturuldu.');
})
.catch(e => {
Alert.alert('Hata', 'Beklenmedik bir hata meydana geldi.');
console.log(e.message);
});
dispatch({
type: ADD_PROJECT_GROUP,
});
};
You are not awaiting groupProfileFinalPic(). This should be done before creating the action you want to dispatch.
groupProfileFinalPic().then(groupProfilePic => {
return firebase
.database()
.ref("/groups/" + key)
.set({
admin: {
email: myUser.email,
name: myUser.name,
uid: myUser.uid
},
groupName,
groupDescription,
groupProfilePic,
projects: ""
})
.then(() => {
console.log("Groups oluşturuldu.");
})
.catch(e => {
Alert.alert("Hata", "Beklenmedik bir hata meydana geldi.");
console.log(e.message);
});
});
I have no clue what the last dispatch is for, you might want to do that in one of the callbacks. Your code is to verbose for an SO question, but I hope this helps anyways.
You are using both await and then on the same call. To use await, you can arrange it something like
const uploadImage = async (imageSource, whereToUpload) => {
...
try {
let data = await RNFS.fs.readFile(uploadUri, 'base64')
let uploadBlob = await Blob.build(data, { type: `${mime};BASE64` }))
...etc...
return finalResult
catch (e) {
// handle error
}
}
I have a Registration form which has many fields for submission.Form submission is working fine, saving all the details to firestore. I have input file upload, user can select multiple files, on submit, uploadin all the files to firebase storage ans saving the upload link in an array(FileURLs).
For Example if I have selected 3 files on submit when i do console.log of state I can see the FileURLs with 3 data but In firestore last value is not getting saved.
Code
handleSubmit = (e) => {
e.preventDefault();
const promises = [];
const {fileURLs,sp_License}=this.state;
let files=[];
let orgFile='';
let err = this.validate();
if (!err) {
this.setState({ loading: true,disChecked:false })
// this.fileupload();
// this.MultifileuploadHandler();
const Lfilename = this.state.sp_Name + '_' + new Date().getTime();
const uploadTask = storage.ref('License/' + Lfilename).put(sp_License);
promises.push(uploadTask);
uploadTask
.then(uploadTaskSnapshot => {
return uploadTaskSnapshot.ref.getDownloadURL();
})
.then(url => {
// orgFile.push({url});
// this.setState({sp_License:url})
orgFile=url
// console.log(orgFile)
},()=>{
console.log(sp_License)
});
//multi pilots file
const storageRef = storage.ref();
this.state.sp_PilotsLicense.forEach((file) => {
const uploadTask= storageRef
.child(`License/${file.name}`).put(file)
promises.push(uploadTask);
uploadTask.then((snapshot) => {
return snapshot.ref.getDownloadURL();
}).then(url =>{
files.push({url});
})
});
Promise.all(promises).then(tasks => {
console.log('all uploads complete');
console.log(this.state)
if(this._mounted)
{
console.log(orgFile)
this.setState({
fileURLs: files,
sp_License:orgFile,
},()=>{
console.log(this.state)
});
}
this.saveData();
});
}
}
saveData=()=>{
let uid = this.props.auth.uid;
let keysToRemove = ["loading", "checked", "disChecked", "open", "message"]
let newState = Object.entries({...this.state}).reduce((obj, [key, value]) => {
if(!keysToRemove.includes(key)){
obj[key] = value
}
return obj
}, {})
console.log(newState)
this.props.UpdateUserDetails(uid, newState,this.successMessage)
}
Action
export const UpdateUserDetails= (id, droneSPDetails,func) => {
console.log(droneSPDetails)
console.log(func)
return (dispatch, getState, { getFirestore }) => {
const firestore = getFirestore()
firestore.collection('users')
.doc(id)
.set({
...droneSPDetails,
sp_RegisteredOn: new Date(),
sp_Status:"pending",
sp_ActiveFlag:"1",
},{ merge: true })
.then(() => {
func();
dispatch({ type: 'CREATE_DRONESP', droneSPDetails });
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
}
This is the value passed to store on firestore (from console.log)
fileURLs: Array(3)
0: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=084bc59a-8087-43de-afdb-05d4192ec4d2"}
1: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=3d427621-6a8b-4ed7-b6ce-5c3940fe7ee6"}
2: {url: "https://firebasestorage.googleapis.com/v0/b/dronew…=media&token=e24a5bab-e584-4a95-bb70-4d6c9f7fed7c"}
length: 3
but I can see only these 2 values getting saved.