skar02
skar02

Reputation: 11

React Native Expo: Base64 Image not uploading to Firebase Storage using any upload method

I am trying to upload a base64 image to Firebase Storage using React Native Expo. The image I am uploading is taken through the takePictureAsync method in expo-camera library with the following CameraPictureOptions

quality:1

base64:true

exif:false 

Next, I store this image in a state variable, named photo, and display it to the user in the app using the Image tag with the uri:

data:image/jpg;base64" + photo.base64

Now when uploading it I first tried the uploadString method as per the firebase storage documentation as below

uploadString(storageRef, photo.base64, 'base64').then((snapshot) => {
  console.log('Uploaded a raw string!');
});

But it gave the error message

Unhandled promise rejection: FirebaseError: Firebase Storage: String does not match format 'base64': Invalid character found (storage/invalid-format)

I tried this with other parameters instead of base64 ("data_url", "base64url", and not putting anything in the parameter), but I got essentially the same error for "data_url" and "base64url", and when I don't put anything in the parameter the app crashes. After this I looked online to find a fix, and one issue that that some people brought up to explain this error message was that to decode and encode the base64 string firebase storage used the atob and btoa method respectively, but this did not work in javascript/was deprecated. To that end, the fix that was suggested was adding this to on top of App.js

import {decode, encode} from 'base-64'; 
if (!global.btoa) { 
   global.btoa = encode; 
} 
if (!global.atob) 
{ 
   global.atob = decode;
}

However, when I did this the app crashed after the button was pressed that triggered the uploadString method.

After this, I tried using the uploadBytes method as per the documentation. I first tried passing the uri string ("data:image/jpg;base64, base64 data) as input, as below. While this did make the image visible on my firebase storage, the image could not be opened. I think this was because this method expected a File or a Blob as input and the input I gave was a base64 string

uploadBytes(storageRef, uri).then((snapshot) => {
  console.log('Uploaded a blob or file!');
});

Next, I looked online for ways to convert the base64 string to a Blob. The first approach I tried was calling the fetch api on uri and the blob function to get the blob and then put that in the uploadBytes function.

const response = await fetch(uri)
const blob = await response.blob() 
uploadBytes(storageRef, blob).then((snapshot) => {
  console.log('Uploaded a blob or file!');
});

However, I get the following error message, which I was unable to solve. Error: ENOENT: no such file or directory, open pathToReactNativeApp/http:/LocalIPAddress:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false'

Next, I tried the following to get the blob as suggested here, but this lead the app to crash.

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"));
          };
          // on complete
          xhr.responseType = "blob";
          xhr.open("GET", uri, true);
          xhr.send(null);
     });

Can someone please guide me on how I can upload this base64 image to firebase storage? Any help would be greatly appreciated!

Upvotes: 1

Views: 875

Answers (2)

Deyvin Cano
Deyvin Cano

Reputation: 1

    xhr.onerror = reject;
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        resolve(xhr.response);
      }
    };
    xhr.open("GET", signature);
    xhr.responseType = "blob";
    xhr.send();

Try this. Been having the same issues but this helped. Solution was posted here.

Upvotes: 0

Hardik
Hardik

Reputation: 1

ImagePicker.launchImageLibraryAsync from expo, will return uri, (no need to include base64 :true)

using that uri generate blob

const response = await fetch(result.uri);

const blob = await response.blob();

using this blob, upload to firebase storage using uploadBytes function

uploadBytes(ref, blob).....

i m using firebase 9 web moduler, will run in all platforms

uploading blob is far batter than using base64 and speedy aswell.

not only images, you can upload videos aswell with this,

Upvotes: -2

Related Questions