0
votes

I uploaded an image using react-native-image-picker's base64 generated data. It shows up on Firebase console fine, but when I try to look at it on my browser, it says "Error Loading Preview" and when I click on it, it is just a black box. See screenshots belowenter image description here enter image description here

Here is my code for the uploading:

const uploadImage = async ({data, filename, uri}) => {
    const ext = uri.split('.').pop();
    const name = uri.split('/').pop();
    const path = `${user.uid}_${name}`;
    const storageRef = firebase.storage().ref(`profiles/${path}`);
    storageRef
        .putString(data, 'base64', {contentType: `image/${ext}`})
        .then(function (snapshot) {
            console.log('SUCCESSSSS');
        });
};
    useEffect(() => {
        ImagePicker.showImagePicker((response) => {
            //console.log('Response = ', response);

            if (response.didCancel) {
                console.log('User cancelled image picker');
            } else if (response.error) {
                console.log('ImagePicker Error: ', response.error);
            } else if (response.customButton) {
                console.log('User tapped custom button: ', response.customButton);
            } else {
                console.log(response.uri);
                uploadImage(response);

                setAvatar({uri: response.uri});
            }
        });
    }, []);

Edit: I copied the base64 string into an online converter, looks good, it gave back the correct image. So there's nothing wrong with the data, it looks like. Something's wrong with how firebase is handling it.

Edit: I tried explicitly setting the type to image/jpeg instead of image/jpg as noted here: Proper way to show image when Firestorage is down or Error loading preview in Firestorage for iOS but no difference.

1

1 Answers

0
votes

Looks like there's more than a few bugs involved with firebase's base64 putString method and react-native: see this thread: https://github.com/firebase/firebase-js-sdk/issues/576. I followed yonahforst's answer and ended up using a blob instead. Worked perfectly.

Copied here in case the thread goes away:

function urlToBlob(url) {
  return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest();
      xhr.onerror = reject;
      xhr.onreadystatechange = () => {
          if (xhr.readyState === 4) {
              resolve(xhr.response);
          }
      };
      xhr.open('GET', url);
      xhr.responseType = 'blob'; // convert type
      xhr.send();
  })
}

Make sure to add the "data:image/jpeg;base64,9asdf92349..." if it's not there. I was using react-native-image-picker, so it didn't have that out of the box.

const dataURL = 'data:image/jpeg;base64,' + data;
    urlToBlob(dataURL).then((blob) => {
        storageRef
            .put(blob)
            .then(function (snapshot) {
                const downloadURL = snapshot.ref.getDownloadURL().then((link) => {
                    console.log('link: ', link);
                    user.updateProfile({photoURL: link});
                });
            })
            .then(() => console.log('SUCCESS'));
    });