i'm trying to upload image selected from expo image picker to firebase storage (since I'm using expo). I checked expo image picker git and found uploadImageAsync for firebase. so I copied it and changed only a little, but somehow it crashes the app most time. Only a few times, it uploaded image properly without any error.
import { storage } from '../firebase'
async function uploadImageAsync(uri, name) {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
const fileRef = ref(storage, `files/${name}`);
const result = await uploadBytes(fileRef, blob);
// We're done with the blob, close and release it
blob.close();
return await getDownloadURL(fileRef);
}
since the uri comes from image in the phone, uri = file:///Users/~absolute path ~/image name.jpg and this is the link expo image picker for firebase expo image picker for firebase
Problem report says, Terminating with uncaught exception of type NSException Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
edit) I found it's working in android but not not in ios
for IOS, I think converting to blob is working. but having error in
const result = await uploadBytes(fileRef, blob)
I also faced the same issue, on firebase version 9.6.5, so i have used function uploadBytesResumable instead of uploadBytes, it works just fine, if it is urgent you can use that function for the time being, just a recommendation, for reference:- https://firebase.google.com/docs/storage/web/upload-files
I faced this issue in iOS 15 and 15 + only, rest below iOS 15 and in android apps uploadBytes is working fine.
Note:- when using XMLHttpRequest with uploadBytesResumable, first time image uploads smoothly on iOS 15.2 then, on uploading it on second time there is crash while uploading image. To avoid it use, const img = await fetch(image_url); const blob = await img.blob();
import { getStorage, ref, getDownloadURL } from "firebase/storage";
const storageRef = ref(getStorage(), "image_name");
const img = await fetch(image_url);
const blob = await img.blob();
console.log("uploading image");
const uploadTask = uploadBytesResumable(storageRef, blob);
// Listen for state changes, errors, and completion of the upload.
uploadTask.on('state_changed',(snapshot) => {
// 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) => {
this.setState({ isLoading: false })
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
switch (error.code) {
case 'storage/unauthorized':
console.log("User doesn't have permission to access the object");
break;
case 'storage/canceled':
console.log("User canceled the upload");
break;
case 'storage/unknown':
console.log("Unknown error occurred, inspect error.serverResponse");
break;
}
},
() => {
// Upload completed successfully, now we can get the download URL
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
//perform your task
});
});