React Native - send image from local cache to firebase storage
We found at least two problems with the way I was trying to retrieve the picture and send it to the Firebase bucket:
1) When retrieving the image from memory and trying to send it as blob
to the bucket, FileSystem.readAsStringAsync(imageUri)
was returning for some reason a corrupted file
2) Instead when trying to save the image to Firebase bucket as base64
, the problem seems to be with firebase, since not even the very same examples provided here https://firebase.google.com/docs/storage/web/upload-files were working.
The solution:
We retrieved the image from local cache with XMLHttpRequest
instead of Expo's FileSystem
, and saved it to Firebase bucket as blob
:
import React, { Component } from 'react';
import firebase from './firebase';
export default async function saveImage(picture, uid) {
const storageRef = firebase
.storage('gs://*<bucket-here>*')
.ref(uid + '/' + 'profile-picture.jpeg');
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', picture.uri, true);
xhr.send(null);
});
const metadata = {
contentType: 'image/jpeg',
};
return (downloadURL = await new Promise((resolve, reject) => {
try {
storageRef.put(blob, metadata).then(snapshot => {
snapshot.ref.getDownloadURL().then(downloadURL => {
resolve(downloadURL);
});
});
} catch (err) {
reject(err);
}
}));
}
How to store Firebase Storage Items to local cache to save bandwidth costs?
You can use CachedNetworkImage
package to avoid downloading the image every time. It's simple to use and you just need to pass the URL to the Widget:
CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
To control how long the image is cached*, make sure you add cache header to your images when you upload them so they get cached properly (in the browser too if you're using flutter web):
final contentType = 'image/*';
final cacheControl = 'public, max-age=31556926'; // seconds -- ie 31556926 == one year
final uploadTask = reference.putData(
image.data,
SettableMetadata(
cacheControl: cacheControl,
contentType: contentType,
));
So make sure to store the URL of the images when you upload them and just pass the URL to the users to get the images instead of downloading the images directly from FirebaseStorage in case you're doing that.
*I believe the package default is 7 days if no cache header is available but I cannot confirm.
Set cache to files in Firebase Storage
cacheControl
for Storage : https://firebase.google.com/docs/reference/js/firebase.storage.SettableMetadata#cacheControl
You'll have better serving with Hosting, and deployment with the firebase CLI is extremely simple. I think by default the Cache-Control on images in Hosting is 2 hours, and you can increase it globally with the .json.
https://firebase.google.com/docs/hosting/full-config#headers
Hosting can scale your site and move it to different edge nodes closer to where the demand is. Storage is limited to buckets, but you can specify a bucket for Europe, one for China, on for North America, etc..
Storage is better for user file uploads and Hosting was for static content (although they are rolling out dynamic Hosting with cloud functions I think)
Related Topics
Android: How to Change the Actionbar "Home" Icon to Be Something Other Than the App Icon
Generate Barcode Image in Android Application
Save Sensitive Data in React Native
How to Change the Android Startactivity() Transition Animation
How to Declare Git Repository as Dependency in Android Gradle
Change the Right Margin of a View Programmatically
Android Retrofit - Onprogressupdate for Showing Progress Notification
Cannot Lower Case Button Text in Android Studio
Filter Output in Logcat by Tagname
How to Capture an Image in Background Without Using the Camera Application
Enabling Wifi on Android Emulator
Multiple Dex Files Define Lorg/Apache/Cordova/Buildhelper
Android: Making a Fullscreen Application
Rate Google Play Application Directly in App
How to Measure Textview Height Based on Device Width and Font Size