React Native非Expo环境下Firebase图片上传报错解决方案咨询
Hey there! Let's work through this upload error you're hitting. The core issue is straightforward: Firebase Storage's put() method requires a Blob or File object to upload, but right now you're passing a local device URI (just a string pointing to the file on your phone). Let's fix this by converting that URI to a Blob and adjusting your code step by step.
Step 1: Add a Helper to Convert URI to Blob
In React Native, you can use the native fetch API to read the local file and turn it into a Blob that Firebase understands. Add this helper function to your component:
const uriToBlob = async (uri) => { try { const response = await fetch(uri); const blob = await response.blob(); return blob; } catch (error) { console.error('Error converting URI to Blob:', error); throw error; } };
This function grabs the file from the device's local path and converts it into the format Firebase needs.
Step 2: Update Your Upload Logic to Use the Blob
Now let's adjust your authentication and upload flow. I also fixed a small issue with your Firestore setup—using a fixed userData document ID will overwrite data for every user, so we'll use the user's unique UID instead:
// Inside your auth and upload workflow: await firebase.auth().createUserWithEmailAndPassword(email, password) .then(async (auth) => { console.log('User created successfully:', auth); // First, convert the image URI to a Blob const profileImageBlob = await uriToBlob(imageURI.uri); // Upload the Blob to Firebase Storage const uploadTask = firebase.storage() .ref(`users/${auth.user.uid}/profileImage.jpg`) .put(profileImageBlob); uploadTask.on( 'state_changed', (snapshot) => { // Optional: Track upload progress (great for user feedback!) const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log(`Upload is ${progress}% complete`); }, (error) => { // Handle upload failures console.error('Storage upload error:', error); Alert.alert('Erro ao fazer upload da foto, tente novamente.'); }, async () => { // Upload finished! Grab the public download URL const downloadURL = await uploadTask.snapshot.ref.getDownloadURL(); // Save user data (including the permanent image URL) to Firestore await db.collection('users') .doc(auth.user.uid) // Use user UID as unique document ID .set({ photo: downloadURL, // Store the public URL, not the local device URI document: params.fileSelected, address: [data], }); setUser(auth); Alert.alert('Cadastro realizado com sucesso!'); } ); }) .catch((error) => { console.error('Authentication error:', error); Alert.alert('Erro ao criar conta, tente novamente.'); });
Key Things to Keep in Mind
- Local URIs are device-only: Storing the phone's local file path in Firestore won't work on other devices (or even after reinstalling the app). Always use the Firebase Storage download URL—it's a permanent, public link to the image.
- Async state updates: In your
handleSelectPicturefunction, theconsole.log('State uri>>>>', imageURI)right aftersetImageURIwill show the old state (since state updates are asynchronous). That's not a bug here, but it's good to remember for future debugging. - Error handling: I added extra error catches to help you debug if something goes wrong during Blob conversion, auth, or upload.
内容的提问来源于stack exchange,提问作者Paulo Rodrigues

