I am currently working on an App. The workflow I currently have is fairly simple.
A user creates an account, and then is taken to a page to populate their profile information. Name, description, and a few images.
I use expo's ImagePicker to get the image:
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 0.1,
allowsEditing: true,
aspect: [2, 3],
base64: true
});
Originally, I was using this to upload the images:
// 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 ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
// We're done with the blob, close and release it
blob.close();
let url = await snapshot.ref.getDownloadURL();
return url;
The problem here is I looped through that function about 6 times, and I kept getting some obscure error.
Currently, I am attempting to upload the images using this:
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.putString(b64Url, "data_url");
This works well on web, but in the native app I get the error:
FirebaseStorageError {
"code_": "storage/invalid-format",
"message_": "Firebase Storage: String does not match format 'base64': Invalid character found",
"name_": "FirebaseError",
"serverResponse_": null,
}
The last comment on this issue outlines the problem. To break it down: atob doesn't exist. This is the sole problem behind the error. To fix, I polyfilled it like this:
import { decode, encode } from "base-64";
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob) {
global.atob = decode;
}
However, the second problem is that:
Firebase also tries to use the native Blob class (implemented by react-native), but the react-native version of Blob incorrectly converts the Uint8Array data to a string, corrupting the upload.
I tried his solution of deleteing global.Blob and restoring it after the upload. Firebase must have become dependent upon blob though, because now it errors out since Edit: Blob is actually being called somewhere in AppEntry.bundle, the uploading works correctly.Blob doesn't exist.
I would like to keep my app in a managed workflow, so I would very much prefer not to eject.
My questions are as follows:
- Where specifically in
react-nativeis the broken Blob code that:
incorrectly converts the Uint8Array data to a string
- Is there a way that I can, while avoiding errors or ejecting, upload 6 images at once to firebase storage? If so, how?