Flutter web - 将图像文件上传到 Firebase 存储
Flutter web - Upload Image File to Firebase Storage
在flutter web上,我从电脑上取一个图片文件,得到一个File图片对象。然后我想将它上传到 Firebase 存储。对于 Android 和 iOS 版本的应用程序,我使用的是 Firebase 云函数和 http 多部分请求。它有效,但对于该应用程序的网络版本却无效。所以,
如何直接或通过 Cloud Function 将 html 图片文件上传到 Firebase 存储?
要在您的 Flutter for Web 应用程序中访问云存储,您可以使用存储库中的 firebase-dart
plugin. You can find an example of accessing storage through firebase-dart
。
最后我设法找到了解决这个问题的办法。为此,我需要安装两个依赖项 firebase and universal_html。
解决办法虽难,实施起来却很简单。这是我用来将 html 图像文件上传到 Firebase 存储的功能代码,进入“图像”文件夹:
import 'dart:async';
import 'package:universal_html/prefer_universal/html.dart' as html;
import 'package:firebase/firebase.dart' as fb;
Future<Uri> uploadImageFile(html.File image,
{String imageName}) async {
fb.StorageReference storageRef = fb.storage().ref('images/$imageName');
fb.UploadTaskSnapshot uploadTaskSnapshot = await storageRef.put(image).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
return imageUri;
}
希望能帮到和我有同样需求的人。
这是适合我上传图片的完整片段:
html.File
对我不起作用,文件已上传,但您会在 firebase 存储中看到 Error loading preview
,因此直接传递字节对我有用。
要显示图像,您可以使用 mediaInfo.bytes
和支持字节的小部件,例如 FadeInImage
您可以使用 MemoryImage(mediaInfo.bytes)
和 Image.memory(mediaInfo.bytes)
使用的包:
Future<MediaInfo> imagePicker() async {
MediaInfo mediaInfo = await ImagePickerWeb.getImageInfo;
return mediaInfo;
}
Future<Uri> uploadFile(
MediaInfo mediaInfo, String ref, String fileName) async {
try {
String mimeType = mime(Path.basename(mediaInfo.fileName));
// html.File mediaFile =
// new html.File(mediaInfo.data, mediaInfo.fileName, {'type': mimeType});
final String extension = extensionFromMime(mimeType);
var metadata = fb.UploadMetadata(
contentType: mimeType,
);
fb.StorageReference storageReference =
fb.storage().ref(ref).child(fileName + ".$extension");
fb.UploadTaskSnapshot uploadTaskSnapshot =
await storageReference.put(mediaInfo.data, metadata).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
print("download url $imageUri");
return imageUri;
} catch (e) {
print("File Upload Error $e");
return null;
}
}
在合并了这么多帖子之后,我做到了,而且成功了!
不,您只是不需要任何一种 Universal_HTML 或另一种 image_picker_web。坚持使用 Image Picker(https://pub.dev/packages/image_picker)。
并使用下面的代码,因为我曾经将图像上传到 Firebase 存储,它在 IOS、Android、Web 上一直有效,我希望你已经添加了 [= 的权限32=] 和 android。让我们开始吧!
Import
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as Path;
Call this method when you want to open a file picker in any of the above platforms!
chooseImage() async {
PickedFile? pickedFile = await ImagePicker().getImage(
source: ImageSource.gallery,
);
}
now you've file in pickedFile use kIsWeb to find out if it's web or not!
uploadImageToStorage(PickedFile? pickedFile) async {
if(kIsWeb){
Reference _reference = _firebaseStorage
.ref()
.child('images/${Path.basename(pickedFile!.path)}');
await _reference
.putData(
await pickedFile!.readAsBytes(),
SettableMetadata(contentType: 'image/jpeg'),
)
.whenComplete(() async {
await _reference.getDownloadURL().then((value) {
uploadedPhotoUrl = value;
});
});
}else{
//write a code for android or ios
}
}
除了 ,您可能还需要更新 index.html 文件以包含新的 firebase 版本。
'src="https://www.gstatic.com/firebasejs/8.6.1/firebase-storage.js">'
void uploadImage({required Function(File? file) onSelected}) {
var uploadInput = FileUploadInputElement()..accept = 'image/*';
uploadInput.click();
uploadInput.onChange.listen((event) async {
final file = uploadInput.files!.first;
final reader = FileReader();
reader.readAsDataUrl(file);
reader.onLoadEnd.listen((event) async {
onSelected(file);
});
});
}
void uploadToStorage() {
final dateTime = DateTime.now();
final userId = FirebaseAuth.instance.currentUser!.uid;
imagePath = '$userId/$dateTime'.replaceAll(' ', '');
uploadImage(onSelected: (file) {
try {
fb.storage().refFromURL('{reference url from firebase}').child(imagePath).put(file);
} catch (e) {
print('uploadImage $e');
}
});
}
点击按钮调用 uploadToStorage 函数并显示图像,
Future<Uri> downloadImageUrl(String? path) {
print(
'downloadImageUrl:: ${fb.storage().refFromURL('{reference url from firebase}').child(path!).getDownloadURL()}');
return fb
.storage()
.refFromURL('gs://onehourappbuildpractice.appspot.com/')
.child(path)
.getDownloadURL();
}
FutureBuilder<Uri>(
future: downloadImageUrl(
controller.hiddenGemList[i].imagePath!),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return Container(
height: 100,
width: 200,
child: FadeInImage.assetNetwork(
image: snapshot.data.toString(),
placeholder: 'assets/placeholder_image.jpeg',
));
})
2022 年的答案
TLDR:在上传之前使用 cross_file 包将您的文件转换为 XFiles。
Select 图片
使用 image_picker 包来 select 图像。这适用于 Android、iOS 和网络。
Future<String?> selectPicture(ImageSource source) async {
XFile? image = await imagePicker.pickImage(
source: source,
maxHeight: 1000,
maxWidth: 1000,
);
return image?.path;
}
将 XFile 转换为 Uint8List
String path = selectPicture(ImageSource.gallery);
Uint8List imageData = await XFile(path).readAsBytes()
将 Uint8List 上传到云存储
UploadTask uploadTask = storageReference.putData(file);
在flutter web上,我从电脑上取一个图片文件,得到一个File图片对象。然后我想将它上传到 Firebase 存储。对于 Android 和 iOS 版本的应用程序,我使用的是 Firebase 云函数和 http 多部分请求。它有效,但对于该应用程序的网络版本却无效。所以,
如何直接或通过 Cloud Function 将 html 图片文件上传到 Firebase 存储?
要在您的 Flutter for Web 应用程序中访问云存储,您可以使用存储库中的 firebase-dart
plugin. You can find an example of accessing storage through firebase-dart
。
最后我设法找到了解决这个问题的办法。为此,我需要安装两个依赖项 firebase and universal_html。 解决办法虽难,实施起来却很简单。这是我用来将 html 图像文件上传到 Firebase 存储的功能代码,进入“图像”文件夹:
import 'dart:async';
import 'package:universal_html/prefer_universal/html.dart' as html;
import 'package:firebase/firebase.dart' as fb;
Future<Uri> uploadImageFile(html.File image,
{String imageName}) async {
fb.StorageReference storageRef = fb.storage().ref('images/$imageName');
fb.UploadTaskSnapshot uploadTaskSnapshot = await storageRef.put(image).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
return imageUri;
}
希望能帮到和我有同样需求的人。
这是适合我上传图片的完整片段:
html.File
对我不起作用,文件已上传,但您会在 firebase 存储中看到 Error loading preview
,因此直接传递字节对我有用。
要显示图像,您可以使用 mediaInfo.bytes
和支持字节的小部件,例如 FadeInImage
您可以使用 MemoryImage(mediaInfo.bytes)
和 Image.memory(mediaInfo.bytes)
使用的包:
Future<MediaInfo> imagePicker() async {
MediaInfo mediaInfo = await ImagePickerWeb.getImageInfo;
return mediaInfo;
}
Future<Uri> uploadFile(
MediaInfo mediaInfo, String ref, String fileName) async {
try {
String mimeType = mime(Path.basename(mediaInfo.fileName));
// html.File mediaFile =
// new html.File(mediaInfo.data, mediaInfo.fileName, {'type': mimeType});
final String extension = extensionFromMime(mimeType);
var metadata = fb.UploadMetadata(
contentType: mimeType,
);
fb.StorageReference storageReference =
fb.storage().ref(ref).child(fileName + ".$extension");
fb.UploadTaskSnapshot uploadTaskSnapshot =
await storageReference.put(mediaInfo.data, metadata).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
print("download url $imageUri");
return imageUri;
} catch (e) {
print("File Upload Error $e");
return null;
}
}
在合并了这么多帖子之后,我做到了,而且成功了!
不,您只是不需要任何一种 Universal_HTML 或另一种 image_picker_web。坚持使用 Image Picker(https://pub.dev/packages/image_picker)。 并使用下面的代码,因为我曾经将图像上传到 Firebase 存储,它在 IOS、Android、Web 上一直有效,我希望你已经添加了 [= 的权限32=] 和 android。让我们开始吧!
Import
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as Path;
Call this method when you want to open a file picker in any of the above platforms!
chooseImage() async {
PickedFile? pickedFile = await ImagePicker().getImage(
source: ImageSource.gallery,
);
}
now you've file in pickedFile use kIsWeb to find out if it's web or not!
uploadImageToStorage(PickedFile? pickedFile) async {
if(kIsWeb){
Reference _reference = _firebaseStorage
.ref()
.child('images/${Path.basename(pickedFile!.path)}');
await _reference
.putData(
await pickedFile!.readAsBytes(),
SettableMetadata(contentType: 'image/jpeg'),
)
.whenComplete(() async {
await _reference.getDownloadURL().then((value) {
uploadedPhotoUrl = value;
});
});
}else{
//write a code for android or ios
}
}
除了
'src="https://www.gstatic.com/firebasejs/8.6.1/firebase-storage.js">'
void uploadImage({required Function(File? file) onSelected}) {
var uploadInput = FileUploadInputElement()..accept = 'image/*';
uploadInput.click();
uploadInput.onChange.listen((event) async {
final file = uploadInput.files!.first;
final reader = FileReader();
reader.readAsDataUrl(file);
reader.onLoadEnd.listen((event) async {
onSelected(file);
});
});
}
void uploadToStorage() {
final dateTime = DateTime.now();
final userId = FirebaseAuth.instance.currentUser!.uid;
imagePath = '$userId/$dateTime'.replaceAll(' ', '');
uploadImage(onSelected: (file) {
try {
fb.storage().refFromURL('{reference url from firebase}').child(imagePath).put(file);
} catch (e) {
print('uploadImage $e');
}
});
}
点击按钮调用 uploadToStorage 函数并显示图像,
Future<Uri> downloadImageUrl(String? path) {
print(
'downloadImageUrl:: ${fb.storage().refFromURL('{reference url from firebase}').child(path!).getDownloadURL()}');
return fb
.storage()
.refFromURL('gs://onehourappbuildpractice.appspot.com/')
.child(path)
.getDownloadURL();
}
FutureBuilder<Uri>(
future: downloadImageUrl(
controller.hiddenGemList[i].imagePath!),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return Container(
height: 100,
width: 200,
child: FadeInImage.assetNetwork(
image: snapshot.data.toString(),
placeholder: 'assets/placeholder_image.jpeg',
));
})
2022 年的答案
TLDR:在上传之前使用 cross_file 包将您的文件转换为 XFiles。
Select 图片
使用 image_picker 包来 select 图像。这适用于 Android、iOS 和网络。
Future<String?> selectPicture(ImageSource source) async {
XFile? image = await imagePicker.pickImage(
source: source,
maxHeight: 1000,
maxWidth: 1000,
);
return image?.path;
}
将 XFile 转换为 Uint8List
String path = selectPicture(ImageSource.gallery);
Uint8List imageData = await XFile(path).readAsBytes()
将 Uint8List 上传到云存储
UploadTask uploadTask = storageReference.putData(file);