Upload base64 image to Google Cloud Storage - Expo/React Native [duplicate] - firebase

Error given: [Unhandled promise rejection: FirebaseError: Firebase Storage: String does not match format 'data_url': Must be formatted 'data:[][;base64], (storage/invalid-format)]
I am able to add image to the database, however it is not uploading to the firebase storage. I have changed it to different media types but no luck. I have also tired uploadBytes instead of uploadString and it works but no image displays. Any help would be appreciated!
const uploadImageTops = async () => {
const docRef = await addDoc(collection(db, "tops"), {
username: "user",
apparel: "tops",
color: "black",
size: size,
timeStamp: serverTimestamp(),
});
const imageRef = ref(storage, `tops/${docRef.id}`);
await uploadString(imageRef, cameraImage, "data_url", {contentType:'image/jpg'})
.then(async (snapshot) => {
const downloadURL = await getDownloadURL(imageRef);
await updateDoc(doc(db, "tops", docRef.id), {
imageUrl: downloadURL,
});
})
.then(navigation.navigate("Home"));
};

There's some issue with react-native and firebase when trying to upload the image. Blob is needed to upload image to firebase storage and firestore. Add that blob at the top and make sure you close the blob at the end.
This code worked for me.
const uploadImageTops = async () => {
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", cameraImage, true);
xhr.send(null);
});
const docRef = await addDoc(collection(db, "tops"), {
username: user,
apparel: "tops",
color: color,
size: size,
timeStamp: serverTimestamp(),
});
const imageRef = ref(storage, `tops/${docRef.id}`);
const metadata = {
contentType: "image/jpeg",
};
await uploadBytes(imageRef, blob, metadata)
.then(async (snapshot) => {
const downloadURL = await getDownloadURL(imageRef);
await updateDoc(doc(db, "tops", docRef.id), {
imageUrl: downloadURL,
});
blob.close();
})
.then(navigation.navigate("Home"));
};

Related

#react-native-firebase/storage -How to upload Image and get the image url

I can upload Image but can't get url into firestore.
I have tried many other people's methods without success...
const uploadImage = async () => {
setUploading(true);
const response = await fetch(image.uri)
const blob = await response.blob();
const filename = image.uri.substring(image.uri.lastIndexOf('/') + 1);
**const imgurl = await getDownloadURL().catch((error) => { throw error });**
var ref = a.storage().ref('math/' + filename).child(filename).put(blob);
console.log("Document successfully written!")
try {
await ref;
} catch (e) {
console.log(e);
}
setUploading(false);
Alert.alert(
'sucess'
);
setImage(null);
db.collection("imageurl").doc().set({
url:imgurl,
})
}

Saved image in Firebase Storage is invalid

Firstly I have to say that I'm using Expo, so from one library I get a data url (I have already checked that it is correct) and then tries to save this image in Firebase Storage, but every time I send it to the base I see the error 'Error loading preview'. I've tried many ways, such as changing it to a Blob using a request, and here I get another error:
[Unhandled promise rejection: TypeError: Network request failed]
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', dataUrl, true);
xhr.send(null);
});
uploadBytes(storageDatabaseReference, blob as Blob).then(() => {
console.log('Uploaded a blob or file!');
});
And there are my previous tries:
const base64result = dataUrl.split(',')[1];
await uploadString(storageDatabaseReference, base64result, 'base64', {
contentType: 'image/png',
}).then(async () => {
const url = await getDownloadURL(storageDatabaseReference);
return url;
});
await uploadString(storageDatabaseReference, dataUrl, 'data_url', {
contentType: 'image/png',
}).then(async () => {
const url = await getDownloadURL(storageDatabaseReference);
return url;
});
for example dataUrl can have value:
data:image/png;base64,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
And this happens always after upload (which works only with uploadString currently):
.

Trying to add a image to firebase V9 storage with react-native expo and redux

Error given: [Unhandled promise rejection: FirebaseError: Firebase Storage: String does not match format 'data_url': Must be formatted 'data:[][;base64], (storage/invalid-format)]
I am able to add image to the database, however it is not uploading to the firebase storage. I have changed it to different media types but no luck. I have also tired uploadBytes instead of uploadString and it works but no image displays. Any help would be appreciated!
const uploadImageTops = async () => {
const docRef = await addDoc(collection(db, "tops"), {
username: "user",
apparel: "tops",
color: "black",
size: size,
timeStamp: serverTimestamp(),
});
const imageRef = ref(storage, `tops/${docRef.id}`);
await uploadString(imageRef, cameraImage, "data_url", {contentType:'image/jpg'})
.then(async (snapshot) => {
const downloadURL = await getDownloadURL(imageRef);
await updateDoc(doc(db, "tops", docRef.id), {
imageUrl: downloadURL,
});
})
.then(navigation.navigate("Home"));
};
There's some issue with react-native and firebase when trying to upload the image. Blob is needed to upload image to firebase storage and firestore. Add that blob at the top and make sure you close the blob at the end.
This code worked for me.
const uploadImageTops = async () => {
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", cameraImage, true);
xhr.send(null);
});
const docRef = await addDoc(collection(db, "tops"), {
username: user,
apparel: "tops",
color: color,
size: size,
timeStamp: serverTimestamp(),
});
const imageRef = ref(storage, `tops/${docRef.id}`);
const metadata = {
contentType: "image/jpeg",
};
await uploadBytes(imageRef, blob, metadata)
.then(async (snapshot) => {
const downloadURL = await getDownloadURL(imageRef);
await updateDoc(doc(db, "tops", docRef.id), {
imageUrl: downloadURL,
});
blob.close();
})
.then(navigation.navigate("Home"));
};

How can I return the download URL of an image uploaded to firebase storage

I want to upload an image to firebase (which is working), then return the download URL of the image and store it as a string.
Here is my code:
uploadImage = async (uri, imageName) => {
const response = await fetch(uri);
const blob = await response.blob();
firebase.storage().ref().child(imageName).put(blob)
.then(snap => {
return snap.ref.getDownloadURL();
})
.then(downloadURL => {
return downloadURL;
})
.catch(error => {
console.log(`An error occurred while uploading the file.\n\n${error}`);
});
}
The image uploads to firebase storage just fine. At the moment it just shows this when I try write the URL of the uploaded image to the database:
https://ibb.co/WHHHxBY
Here is the block of code where I create the user record:
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(userCredentials => {
let imageUrl = '';
let db = firebase.database().ref('users/' + userCredentials.user.uid);
if (this.state.image) {
imageUrl = this.uploadImage(this.state.image.uri, `images/user-${userCredentials.user.uid}`);
}
db.set({
email: this.state.email,
imageUrl: imageUrl,
username: this.state.username
});
return userCredentials.user.updateProfile({
displayName: this.state.username
});
})
.catch(error => this.setState({ errorMessage: error.message }));
In your uploadImage function, you are chaining the promises but you don't return the chain. You should adapt it as follows:
uploadImage = async (uri, imageName) => {
const response = await fetch(uri);
const blob = await response.blob();
return firebase.storage().ref().child(imageName).put(blob) // <-- Here return the chain
.then(snap => {
return snap.ref.getDownloadURL();
})
.then(downloadURL => {
return downloadURL;
})
.catch(error => {
console.log(`An error occurred while uploading the file.\n\n${error}`);
});
}
However, you could transform this code in async/await "style", as follows:
uploadImage = async (uri, imageName) => {
try {
const response = await fetch(uri);
const blob = await response.blob();
const snap = await firebase.storage().ref().child(imageName).put(blob);
const downloadURL = await snap.ref.getDownloadURL();
return downloadURL;
} catch (e) {
console.error(e);
throw e;
}
}
Then, since this uploadImage function is asynchronous you should adapt the way you call it. I suggest to modify the other part of your code as follows:
try {
const userCredentials = await firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password);
let imageUrl = '';
const db = firebase.database().ref('users/' + userCredentials.user.uid);
if (this.state.image) {
imageUrl = await this.uploadImage(this.state.image.uri, `images/user-${userCredentials.user.uid}`);
await db.set({
email: this.state.email,
imageUrl: imageUrl,
username: this.state.username
});
return userCredentials.user.updateProfile({
displayName: this.state.username
});
}
//You should probably manage the else case
} catch (e) {
this.setState({ errorMessage: e.message })
}

When I am uploading a image to firebase through expo react native it is not showing the image; error loading preview is shown

I am uploading a image without base 64 in firebase using expo. The file is uploaded but I can't view the image - "Error loading preview". When I try to download the image through the url it shows me corrupted or broken image.
My code of firebase uploading is :
async function uploadImageAsync(itemImage, passedParameter, ItemName, ItemDesc, ItemPrice, ItemWeight) {
const response = await fetch(itemImage);
const blob = await response.blob();
console.log("uri of the elements ius", blob)
var storageRef = firebase.storage().ref();
var file = blob
var metadata = {
contentType: 'image/jpeg',
};
const timeStamp = Date.now();
var uploadTask = storageRef.child('CategoryDescription' + "/" + `${passedParameter}` + "/" + `${ItemName}`).put(file, metadata);
And expo image picker code is:
_pickImage = async () => {
const { CAMERA, CAMERA_ROLL } = Permissions;
const permissions = {
[CAMERA]: await Permissions.askAsync(CAMERA),
[CAMERA_ROLL]: await Permissions.askAsync(CAMERA_ROLL),
};
if (permissions[CAMERA].status === 'granted' && permissions[CAMERA_ROLL].status === 'granted') {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: false,
aspect:[4,3],
quality: 0.5,
});
// console.log(result);
if (!result.cancelled) {
this.setState({ itemImage: result.uri });
}
}
Please help!
I have the same problem before. I found that it's because launchImageLibraryAsync setting and blob format isn't image. You can try to use base64.
First of all, set launchImageLibraryAsync option as fellow:
const result = await ImagePicker.launchCameraAsync({
allowsEditing: true,
base64: true,
aspect: [4, 3]
})
Secondly, upload base64 to firebase:
export const uploadAsFile = (base64, folder: string) => {
var metadata = {
contentType: 'image/jpeg'
}
let name = new Date().getTime() + '-media.jpg'
const ref = firebase
.storage()
.ref()
.child(folder + '/' + name)
const task = ref.putString(base64, 'base64', metadata)
return new Promise((resolve, reject) => {
task.on(
'state_changed',
snapshot => {},
error =>
reject(error) /* this is where you would put an error callback! */,
() => {
const downloadURL = task.snapshot
console.log('downloadURL:', downloadURL, name)
resolve(name)
}
)})
}

Resources