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

13

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

 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库编写Flutter等效代码的方法,这个库https://pub.dartlang.org/packages/cloud_firestore没有FirebaseFirestoreSettings的等效项(或者我似乎找不到)。 有没有解决这个问题的方法?
谢谢!
4个回答

10

更新了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();

因为错误:类'StorageUploadTask'没有定义'future'的getter方法(undefined_getter at [timetracker] lib/screens/image_detection.dart:63)


这个可以运行。但是如果在短时间内上传第二张图片,应用程序就会崩溃。 - Yarm
为什么会失败?如何修复? - SacWebDeveloper
FYI:'ImagePicker.pickImage'已弃用,不应使用。改用ImagePicker.getImage()方法--这也意味着你必须将类型File更改为PickedFile(例如,PickedFile imageFile = await ImagePicker.getImage(...))。 - Sludge

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;
}

似乎有相同的问题 :( - Marko
一旦图像被存储,您可以使用 Image.network(uriOfImage).image 显示它。 - mmccabe

2

这对我有用...在我的情况下,我还需要获取下载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());


}

0
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();
}

目前为止,

这会报错:

return await (await uploadTask.onComplete).ref.getDownloadURL();

而这不会:

return (await uploadTask.onComplete).ref.getDownloadURL();

错误信息:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接