Firebase Storage: string does not match format base64: invalid character found. Only when debug is off

Firebase Storage: string does not match format base64: invalid character found. Only when debug is off



I'm trying to upload an image file to firebase storage, save the download URL, and load it after the upload is completed. When I run the app with debug js remotely on it works fine. When I turn off debug mode it stops working with the invalid format exception. The same happens when I run in a real device (both iOS and Android)



The base64 response data from React Native Image Picker seems to be correct



Here's my code


...
import * as ImagePicker from 'react-native-image-picker'; //0.26.10
import firebase from 'firebase'; //4.9.1
...

handleImagePicker = () =>
const me = this.props;
const options =
title: 'Select pic',
storageOptions:
skipBackup: true,
path: 'images'
,
mediaType: 'photo',
quality: 0.5,
;
ImagePicker.showImagePicker(options, async (response) =>
const storageRef = firebase.storage().ref(`/profile-images/user_$me.id.jpg`);

const metadata =
contentType: 'image/jpeg',
;

const task = storageRef.putString(response.data, 'base64', metadata);
return new Promise((resolve, reject) =>
task.on(
'state_changed',
(snapshot) =>
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
,
(error) =>
console.log(error),
() =>
this.onChangeProfileImage();

);
);



onChangeProfileImage = async () =>
const me = this.props;

const storageRef = firebase.storage().ref(`/profile-images/user_$me.id.jpg`);

const profileImageUrl = await new Promise((resolve, reject) =>
storageRef.getDownloadURL()
.then((url) =>
resolve(url);
)
.catch((error) =>
console.log(error);
);
);


// some more logic to store profileImageUrl in the database




Any idea how to solve this?



Thanks in advance.




1 Answer
1



After some research and debug I found the cause of the issue and a solution for it.



Firebase uses atob method to decode the base64 string sent by putstring method.
However, since JavaScriptCore doesn't have a default support to atob and btoa, the base64 string can't be converted, so this exception is triggered.


atob


putstring


atob


btoa



When we run the app in debug javascript remotely mode, all javascript code is run under chrome environment, where atob and btoa are supported. That's why the code works when debug is on and doesn't when its off.


atob


btoa



To handle atob and btoa in React Native, we should either write our own encode/decode method, or install a lib to handle it for us.


atob


btoa



In my case I preferred to install base-64 lib


base-64



But here's an example of a encode/decode script:


const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const Base64 =
btoa: (input:string = '') => 0) ,

atob: (input:string = '') =>
let str = input.replace(/=+$/, '');
let output = '';

if (str.length % 4 == 1)
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");

for (let bc = 0, bs = 0, buffer, i = 0;
buffer = str.charAt(i++);

~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
)
buffer = chars.indexOf(buffer);


return output;

;

export default Base64;



Usage:


import Base64 from '[path to your script]';

const stringToEncode = 'xxxx';
Base64.btoa(scriptToEncode);

const stringToDecode = 'xxxx';
Base64.atob(stringToDecode);



After choosing either to use the custom script or the lib, now we must add the following code to the index.js file:


index.js


import decode, encode from 'base-64';

if (!global.btoa)
global.btoa = encode;


if (!global.atob)
global.atob = decode;


AppRegistry.registerComponent(appName, () => App);



This will declare atob and btoa globally. So whenever in the app those functions are called, React Native will use the global scope to handle it, and then trigger the encode and decode methods from base-64 lib.


atob


btoa


encode


decode


base-64



So this is the solution for Base64 issue.



However, after this is solved, I found another issue Firebase Storage: Max retry time for operation exceed. Please try again when trying to upload larger images. It seems that firebase has some limitation on support to React Native uploads, as this issue suggests.


Firebase Storage: Max retry time for operation exceed. Please try again


firebase



I believe that react-native-firebase may not struggle on this since it's already prepared to run natively, instead of using the web environment as firebase does. I didn't test it yet to confirm, but it looks like this will be the best approach to handle it.


react-native-firebase


firebase



Hope this can be helpful for someone else.





Brilliant, it works! BTW, I used github.com/dankogai/js-base64
– Yossi
Nov 13 '18 at 21:26





BTW, @soutot, did you use fetch() for reading the file from cache? It didn't work for me, so I am trying to use expo's FileSystem.readAsStringAsync instead.
– Yossi
Nov 13 '18 at 21:32





I started working on other projects and didn't finish this one, so I haven't implemented cache reading. My idea at that time was to download the image and store in the local storage. Then read from it if there's any valid image stored, otherwise fetch again. I think it might work.
– soutot
Nov 13 '18 at 23:52





Well, good luck :) fetch seemed to work for me for a while, and then stopped working. github.com/expo/firebase-storage-upload-example/issues/14
– Yossi
Nov 14 '18 at 5:39



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)