如何使用 Flutter 将图像上传到 Firebase

Posted

技术标签:

【中文标题】如何使用 Flutter 将图像上传到 Firebase【英文标题】:How to upload image to Firebase using Flutter 【发布时间】:2018-12-22 00:38:05 【问题描述】:

我正在使用 image_picker 库 https://pub.dartlang.org/packages/image_picker 来选择/拍摄我要上传的照片。到目前为止的代码成功地将图像上传到 Firebase 存储,唯一的问题是图像上传后应用程序关闭(并没有真正崩溃,它只是关闭并且 VS 代码失去了与设备的连接)。代码如下:

 File _image;

  Future _takeProfilePicture() async
    var image = await ImagePicker.pickImage(source: ImageSource.camera);

    setState(()
      _image = image;
    );
  

  Future _selectProfilePicture() async
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);

    setState(()
      _image = image;
    );
  

  Future<Null> _uploadProfilePicture() async
    FirebaseUser user = await FirebaseAuth.instance.currentUser();

    final StorageReference ref = FirebaseStorage.instance.ref().child('$user.email/$user.email_profilePicture.jpg');
    final StorageUploadTask uploadTask = ref.putFile(_image);
    final Uri downloadUrl = (await uploadTask.future).downloadUrl;
  

  void _selectAndUploadPicture() async
    await _selectProfilePicture();
    await _uploadProfilePicture();
  

  void _takeAndUploadPicture() async
    await _takeProfilePicture();
    await _uploadProfilePicture();
  

终端打印以下内容:

W/Firestore( 6873): (0.6.6-dev) [Firestore]: The behavior for java.util.Date objects stored in Firestore is going to change AND YOUR APP MAY BREAK.
W/Firestore( 6873): To hide this warning and ensure your app does not break, you need to add the following code to your app before calling any other Cloud Firestore methods:
W/Firestore( 6873):
W/Firestore( 6873): FirebaseFirestore firestore = FirebaseFirestore.getInstance();
W/Firestore( 6873): FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
W/Firestore( 6873):     .setTimestampsInSnapshotsEnabled(true)
W/Firestore( 6873):     .build();
W/Firestore( 6873): firestore.setFirestoreSettings(settings);
W/Firestore( 6873):
W/Firestore( 6873): With this change, timestamps stored in Cloud Firestore will be read back as com.google.firebase.Timestamp objects instead of as system java.util.Date objects. So you will also need to update code expecting a java.util.Date to instead expect a Timestamp. For example:
W/Firestore( 6873):
W/Firestore( 6873): // Old:
W/Firestore( 6873): java.util.Date date = snapshot.getDate("created_at");
W/Firestore( 6873): // New:
W/Firestore( 6873): Timestamp timestamp = snapshot.getTimestamp("created_at");
W/Firestore( 6873): java.util.Date date = timestamp.toDate();
W/Firestore( 6873):
W/Firestore( 6873): Please audit all existing usages of java.util.Date when you enable the new behavior. In a future release, the behavior will be changed to the new behavior, so if you do not follow these steps, YOUR APP MAY BREAK.

我尝试从终端实现建议的 java 代码,但我似乎找不到使用 cloud_firestore 库 https://pub.dartlang.org/packages/cloud_firestore 在颤振中编写等效代码的方法,它没有与 FirebaseFirestoreSettings 等效的代码(或者我似乎找不到一)。有没有办法解决这个问题?

提前谢谢你!

【问题讨论】:

【参考方案1】:

mmccabe 答案的更新版本,适用于 firebase_storage 插件的 1.0.4 版本

Future<String> _pickSaveImage(String imageId) async 
  File imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  StorageReference ref =
    FirebaseStorage.instance.ref().child(imageId).child("image.jpg");
  StorageUploadTask uploadTask = ref.putFile(imageFile);
  return await (await uploadTask.onComplete).ref.getDownloadURL();

现在你必须做的:

var downloadURL = (await uploadTask.onComplete).ref.getDownloadURL();

因为error: The getter 'future' isn't defined for the class 'StorageUploadTask'. (undefined_getter at [timetracker] lib/screens/image_detection.dart:63)

【讨论】:

这行得通。但是如果连续快速上传第二张图片,那么应用就会崩溃。 为什么会失败?如何解决? 仅供参考:'ImagePicker.pickImage' 已弃用,不应使用。请改用 ImagePicker.getImage() 方法——这也意味着您必须将类型 File 更改为 PickedFile(例如,PickedFile imageFile = await ImagePicker.getImage(...)【参考方案2】:

以下对我有用:

Future<Uri> _pickSaveImage(String imageId) async 
  File imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  StorageReference ref =
    FirebaseStorage.instance.ref().child(imageId).child("image.jpg");
  StorageUploadTask uploadTask = ref.putFile(imageFile);
  return (await uploadTask.future).downloadUrl;

【讨论】:

似乎有同样的问题:( 图像存储后,您可以使用Image.network(uriOfImage).image显示它。【参考方案3】:

这对我有用...在我的情况下,我还需要获取下载 URL 并推送到 firestore 集合。在做了一些阅读后,我发现最好使用 StorageTaskSnapshot 然后获取下载 URL

uploadImage(File image) async 
    StorageReference reference =
             FirebaseStorage.instance.ref().child(image.path.toString());
    StorageUploadTask uploadTask = reference.putFile(image);

    StorageTaskSnapshot downloadUrl = (await uploadTask.onComplete);

    String url = (await downloadUrl.ref.getDownloadURL());



【讨论】:

【参考方案4】:
Future<String> _pickSaveImage(String imageId) async 
  File imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  StorageReference ref =
    FirebaseStorage.instance.ref().child(imageId).child("image.jpg");
  StorageUploadTask uploadTask = ref.putFile(imageFile);
  return await (await uploadTask.onComplete).ref.getDownloadURL();

截至目前,

这会报错:

返回等待(await uploadTask.onComplete).ref.getDownloadURL();

这不是:

返回(等待uploadTask.onComplete).ref.getDownloadURL();

错误信息:

The getter 'future' isn't defined for the class 'StorageUploadTask'. 

undefined_getter at [timetracker] lib/screens/image_detection.dart:63)

【讨论】:

以上是关于如何使用 Flutter 将图像上传到 Firebase的主要内容,如果未能解决你的问题,请参考以下文章

Flutter AZURE BLOB IMAGE UPLOAD - 如何将使用移动相机拍摄的图像上传到 azure blob 存储

如何将多个图像上传到 Flutter 中的 REST API?

使用 Flutter (iOS/Android) 将图像上传到 Azure blob

使用 Flutter 将图像上传到通用 Google Drive 帐户

如何使用 HTTP 将多张图片上传到 Flutter 中的 Rest API?

Flutter - 将图像上传到 Firebase 存储