firebase-js-sdk
firebase-js-sdk copied to clipboard
uploadBytes to storage with expo Image picker causing app to crash with no logs
[REQUIRED] Describe your environment
- Operating System version: iOS 14.8.1
- Expo CLI 5.0.3 environment info: System: OS: macOS Sierra 10.12.6 Shell: 3.2.57 - /bin/bash Binaries: Node: 12.16.2 - /usr/local/bin/node npm: 6.14.4 - /usr/local/bin/npm SDKs: iOS SDK: Platforms: iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0 npmPackages: expo: ~44.0.0 => 44.0.1 react: 17.0.1 => 17.0.1 react-dom: 17.0.1 => 17.0.1 react-native: 0.64.3 => 0.64.3 react-native-web: 0.17.1 => 0.17.1 npmGlobalPackages: expo-cli: 5.0.3
- Firebase SDK version: 9.6.1
- Firebase Product: storage (auth, database, storage, etc)
[REQUIRED] Describe the problem
I am using Expo Image picker to select an image, convert to blob, then the Firebase 9.0 SDK function uploadBytes to add the image to my storage bucket. Around 60-80% of the time, the uploadBytes function causes my app to crash with no errors or logs recorded. When the app does not crash, the upload to Storage is successful.
Similar code and crashing symptoms as: https://stackoverflow.com/questions/70528896/react-native-expo-image-picker-upload-image-to-firebase-storage-v9-crash
Steps to reproduce:
Relevant Code:
const uploadNewPhoto = async() => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
// aspect: [4, 3],
quality: 0.1,
});
if (!result.cancelled) {
// Convert URI to a Blob via XHTML request, and actually upload it to the network
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function() {
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', result.uri, true);
xhr.send(null);
});
const thisUsersNewPostRef = ref(storageRef, 'users/img1' );
uploadBytes(thisUsersNewPostRef, blob).then((snapshot) => { // causes crash
console.log('Uploaded a blob or file!');
});
}
}
Hello! In order to solve your issue, I first recommend that you update to the latest version of firebase (v9) within your Expo application. Then, watch this video: https://www.youtube.com/watch?v=H-yXO46WDak . Very recent video so it incorporates version 9 and also should solve your issue because it also tries to upload image to firebase storage. Hope this helps!
When looking at your code, I believe that it is the method that you use to generate the blob is complicated and prone to errors. Reference the video I just sent to see how I recommend you turn your image into a blob.
@Eesha-Jain Your YouTube code works for images through ImagePicker but not for videos. It always crashes on iOS videos. Android videos go through just fine.
Ohh, alright. Looks like this may hold a solution: https://github.com/expo/expo/issues/3177
@rgioeli hey, I am having the same issue - did you end up finding a solution that worked for you?
@rgioeli hey, I am having the same issue - did you end up finding a solution that worked for you?
I downgraded to v8 of firebase sdk, that worked for me. Not sure if it's an option for you, but maybe for other people reading this.
As described in the comment at https://www.youtube.com/watch?v=H-yXO46WDak&lc=UgwNOcXKFQl2UARHz6Z4AaABAg.9Wqk13KYbzW9WuNC4HWz_s
@pfibbe I just saw that mentioned somewhere else as well - seems like the way to go. Thanks!
Thanks for the info that this works with 8.10.0 and not in 9.6.1. Would anybody be able to try and see if this is also broken in any earlier v9 builds, such as 9.2.0 perhaps? It would help us narrow down when the relevant change happened.
I was actually using 9.2.0 when I came across the issue.
Does the error also occur in 9.0.0?
Unsure - unfortunately, I won't be able to check for a while, sorry.
I would recommend going to 8.10.0 cause we're sure that works
However, trying won't do any harm! :)
Same issue, some video files fail randomly.
If anyone can confirm the error also occurs in 9.0.0 and does not occur in 8.10.0, it will help us a lot in narrowing down the change that caused it.
I will test it now with specific version of 9.0.0. It was definitely not working with ^9.2.0, then I switched back to 8.10.0 as mentioned here) and it was not working either. That being said, only with certain videos. Probably, as mentioned coz of memory issues with not small videos.
If anyone can confirm the error also occurs in 9.0.0 and does not occur in 8.10.0, it will help us a lot in narrowing down the change that caused it.
Hello, everyone 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 OS 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();
this way we can also get blob file;
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
});
});
If anyone can confirm the error also occurs in 9.0.0 and does not occur in 8.10.0, it will help us a lot in narrowing down the change that caused it.
well i was using v9.4 then i upgrade it to latest version. i was able to upload file less than 2mb ... greater files will make the app crash
so i went down to version 9.0.0 and i was able to upload files at 100mb+ so i think this issue related to newer versions of firebase.
Will keep trying to dig into this but so far it seems that this error:
- affects larger files
- can be avoided by using
uploadBytesResumable()
instead ofuploadBytes()
- can also be avoided by using
fetch()
instead ofXMLHttpRequest
to get the image from the Expo image picker url
It seems 2 and 3 may be viable workarounds for the time being if anyone is blocked.
As far as more info about versions affected, it seems to affect:
- iOS 15+
- Firebase JS SDK 9.2.0 ?? +
Feel free to chime in with any corrections, updates, or other workarounds. We will try to keep looking for what might have caused this in the Firebase SDK.
I am experiencing this issue as well.
- This is in an expo managed app.
- The error only appears on videos longer than about 10 seconds @ 720p.
- I am using fetch to retrieve the blob before upload.
- I experience it both with
uploadBytesResumable
where it crashes without error after a few seconds. AnduploadBytes
where it crashes immediately.
I have pinpointed that I can rollback to Firebase JS SDK 9.3.0 and everything works as expected, but upgrading to 9.4.1 - 9.6.6 causes the failure to occur. So for our experience it's something introduced between 9.3.0 and 9.4.1.
The code that i wrote above is running fine on my mac but when complied from my colleague's pc created the same issue. We were still not able to resolve it by downgrading firebase version. I don't think issue lies in firebase sdk. It's just that it is not compatible with iOS 15 ?? + (because i only faced this issue in iOS 15). Maybe a support for iOS 15 needs to be added as iOS 15 has come up with major updations. Just a guess. Try to solve issue by changing firebase version and maybe compiling your code on other device. I will still recommend to use uploadResumable bytes and fetch.
How would i rollback to a different version of FIREBASE?
How would i rollback to a different version of FIREBASE? you will need to use name and version of the package npm install [email protected]
async function uploadImageAsync(uri, title, index) {
// Why are we using XMLHttpRequest? See:
// https://github.com/expo/expo/issues/2402#issuecomment-443726662
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
const fileRef = ref(storage, `images/events/${title}/image${index}`);
const result = await uploadBytesResumable(fileRef, blob);
// We're done with the blob, close and release it
blob.close();
return await getDownloadURL(fileRef);
}
Been using the above code to upload images to firebase (version 9.6.6). Works perfectly with one image, but cannot upload multiple images. Any suggestions? Have tried using await and .then() to try looping, but that has not worked either.
So we have one report that the bug occurred in 9.2.0, and a separate report that it did not occur in 9.3.0 but did occur in 9.4.1, which seems confusing to me. Any additional data about what versions the error is or isn't happening would be helpful in sorting out what changes to look at.
async function uploadImageAsync(uri, title, index) { // Why are we using XMLHttpRequest? See: // https://github.com/expo/expo/issues/2402#issuecomment-443726662 const blob = await new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.onload = function () { resolve(xhr.response); }; xhr.onerror = function (e) { reject(new TypeError("Network request failed")); }; xhr.responseType = "blob"; xhr.open("GET", uri, true); xhr.send(null); }); const fileRef = ref(storage, `images/events/${title}/image${index}`); const result = await uploadBytesResumable(fileRef, blob); // We're done with the blob, close and release it blob.close(); return await getDownloadURL(fileRef); }
Been using the above code to upload images to firebase (version 9.6.6). Works perfectly with one image, but cannot upload multiple images. Any suggestions? Have tried using await and .then() to try looping, but that has not worked either.
Use this code to get blob file instead of XMLHttpRequest
const img = await fetch(uri);
const blob = await img.blob();
So we have one report that the bug occurred in 9.2.0, and a separate report that it did not occur in 9.3.0 but did occur in 9.4.1, which seems confusing to me. Any additional data about what versions the error is or isn't happening would be helpful in sorting out what changes to look at.
I can confirm that I stepped through minor versions one-by-one until it started occurring and it first started in 9.4
This is on managed Expo app served through the Expo app. The impact on iOS it uploads for a bit then crashes without error. On Android, it uploads for a bit then hangs forever without error. This testing was done on real devices, not simulators.
I only stepped through the individual versions within the Expo app but can also verify it worked in 9.0 when deployed through the official stores, and was broken in 9.6. On both platforms.
Hello, I'm having the same issue, but I might be able to add some insight. Here is my current takePicture function:
const takePicture = async () => { if (cameraRef.current) { const options = { quality: 0.1, base64: true, skipProcessing: true }; const data = await cameraRef.current.takePictureAsync(options); const source = data.uri if (source) { navigateToSave(source) } } };
I'm also using the Full Example from the Firebase Upload Files documentation.
With the current options, I am able to upload both images from the camera to Firebase. However, if I remove the quality option, the upload fails 100% of the time. It would seem that the size of the file might cause uploadBytesResumable to crash.
Using Firebase v9.6.6
and Expo v43.0.0
; Windows 10 and Expo Go.
There's 2 reports indicating this may have started in 9.4.1, and if so, this would be the relevant commit: https://github.com/firebase/firebase-js-sdk/pull/5703 Will try to take a closer look.
There's 2 reports indicating this may have started in 9.4.1, and if so, this would be the relevant commit: #5703 Will try to take a closer look.
I can confirm that I have the problem with 9.2.0 and above (including 9.3.0). I haven't been able to test yet with 9.0.0 and 9.1.0.