如何将 Firebase 存储项存储到本地缓存以节省带宽成本?
How to store Firebase Storage Items to local cache to save bandwidth costs?
我注册了一个使用 Flutter 和 Firebase 的项目,但我遇到了带宽限制方面的问题。免费配额是每天 1gb,我有一个包含 100 张图像(和一些文件)的列表。
有没有一种方法可以通过在本地 phone 缓存中缓存这些文件来最小化带宽成本,从而不必在每次打开屏幕时都从数据库中获取项目?
是否有软件包或类似的东西可以做到这一点?
我想你可以用 cached network image
轻松做到
如果你想要更多的控制,我创建了一个简单的函数来完成这项工作,你可以根据你的需要进一步定制它:
import 'dart:typed_data';
import 'dart:io';
import 'package:http/http.dart' show get;
Future<File> getCachedImageFile(final String imageId) async {
final Directory temp = await getTemporaryDirectory();
final String fullPathName = '${temp.path}/images/$imageId';
final File imageFile = File(fullPathName);
if (imageId == null) return null;
if (await imageFile.exists() == false) { // will guarantee that you don't make the API request (or just get image from url if unprotected)
final String endpoint = 'http://www.mywebsiteorRESTapi.com/'
String imgUrl = endpoint + imageId + '.png';
var response = await get(imgUrl);
try {
await imageFile.create(recursive: true);
if (response.bodyBytes != null)
await imageFile.writeAsBytes(response.bodyBytes);
return imageFile;
} on Exception catch (exception) {
throw 'could not write image $exception';
}
}
return imageFile;
}
在你的 FutureBuilder 中:
future: getCachedImageFile('1VsSbB4Kh7Ab7spjQBA');
...
return Image.file(snapshot.data)
您可以使用CachedNetworkImage
package来避免每次都下载图片。它使用起来很简单,你只需要将 URL 传递给 Widget:
CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
要控制图像的缓存时间*,请确保在上传图像时将缓存 header 添加到图像中,以便正确缓存它们(如果您使用的是 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,
));
因此,请确保在上传图像时存储图像的 URL,并将 URL 传递给用户以获取图像,而不是直接从 FirebaseStorage 下载图像,以防万一正在这样做。
*如果没有可用的缓存 header,我相信包默认为 7 天,但我无法确认。
我注册了一个使用 Flutter 和 Firebase 的项目,但我遇到了带宽限制方面的问题。免费配额是每天 1gb,我有一个包含 100 张图像(和一些文件)的列表。
有没有一种方法可以通过在本地 phone 缓存中缓存这些文件来最小化带宽成本,从而不必在每次打开屏幕时都从数据库中获取项目?
是否有软件包或类似的东西可以做到这一点?
我想你可以用 cached network image
轻松做到如果你想要更多的控制,我创建了一个简单的函数来完成这项工作,你可以根据你的需要进一步定制它:
import 'dart:typed_data';
import 'dart:io';
import 'package:http/http.dart' show get;
Future<File> getCachedImageFile(final String imageId) async {
final Directory temp = await getTemporaryDirectory();
final String fullPathName = '${temp.path}/images/$imageId';
final File imageFile = File(fullPathName);
if (imageId == null) return null;
if (await imageFile.exists() == false) { // will guarantee that you don't make the API request (or just get image from url if unprotected)
final String endpoint = 'http://www.mywebsiteorRESTapi.com/'
String imgUrl = endpoint + imageId + '.png';
var response = await get(imgUrl);
try {
await imageFile.create(recursive: true);
if (response.bodyBytes != null)
await imageFile.writeAsBytes(response.bodyBytes);
return imageFile;
} on Exception catch (exception) {
throw 'could not write image $exception';
}
}
return imageFile;
}
在你的 FutureBuilder 中:
future: getCachedImageFile('1VsSbB4Kh7Ab7spjQBA');
...
return Image.file(snapshot.data)
您可以使用CachedNetworkImage
package来避免每次都下载图片。它使用起来很简单,你只需要将 URL 传递给 Widget:
CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
要控制图像的缓存时间*,请确保在上传图像时将缓存 header 添加到图像中,以便正确缓存它们(如果您使用的是 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,
));
因此,请确保在上传图像时存储图像的 URL,并将 URL 传递给用户以获取图像,而不是直接从 FirebaseStorage 下载图像,以防万一正在这样做。
*如果没有可用的缓存 header,我相信包默认为 7 天,但我无法确认。