Flutter 上传一批图像并获取所有这些 URL 以存储在 Firestore 中

Posted

技术标签:

【中文标题】Flutter 上传一批图像并获取所有这些 URL 以存储在 Firestore 中【英文标题】:Flutter Upload batch of images and get all those URLs to store in Firestore 【发布时间】:2019-04-10 12:07:24 【问题描述】:

我正在尝试将 n 张照片上传到 Firebase 存储并将这些 URL 保存在 Firestore 内的数组中,但我无法获得 downloadURL() 或者我不知道在哪里可以找到它。我检查了其他答案,但那些是针对单个文件的,我正在尝试上传一批并将 URL 存储在一起,而不是上传并将 URL 存储到 Firestore 等等......

代码:

_uploadImages(String userID, String productID, List<File> images, Function onSuccess(List<String> imageURLs), Function onFailure(String e)) 
    List<String> imageURLs = [];
    int uploadCount = 0;

    StorageReference storeRef = FirebaseStorage.instance.ref().child('Products').child(userID).child(productID).child(uploadCount);
    StorageMetadata metaData = StorageMetadata(contentType: 'image/png');

    images.forEach((image) 
      storeRef.putFile(image, metaData).onComplete.then((snapshot) 
        STUCK AT THIS POINT SINCE THE SNAPSHOT DOESN'T SHOW THE URL OPTION...
        //imageURLs.add(snapshot. )
        uploadCount++;

        if (uploadCount == images.length) 
          onSuccess(imageURLs);
        
      );
    );
  

【问题讨论】:

【参考方案1】:

这些解决方案不适用于 firebase_storage: ^5.0.1 as await uploadTask.onComplete; 不再适用。如果您升级了应用程序,请提出任何其他解决方案。谢谢

【讨论】:

【参考方案2】:

我尝试了标记的答案对我不起作用,所以我深入挖掘并设法用 for 循环做到了

 List<File> _imageList = List();
//add selected images to list
 _imageList.add(_image);
      Future uploadMultipleImages() async 

    List<String> _imageUrls = List();




    try 
      for (int i = 0; i < _imageList.length; i++) 
        final StorageReference storageReference = FirebaseStorage().ref().child("multiple2/$i");

        final StorageUploadTask uploadTask = storageReference.putFile(_imageList[i]);

        final StreamSubscription<StorageTaskEvent> streamSubscription =
            uploadTask.events.listen((event) 
          // You can use this to notify yourself or your user in any kind of way.
          // For example: you could use the uploadTask.events stream in a StreamBuilder instead
          // to show your user what the current status is. In that case, you would not need to cancel any
          // subscription as StreamBuilder handles this automatically.

          // Here, every StorageTaskEvent concerning the upload is printed to the logs.
          print('EVENT $event.type');
        );

        // Cancel your subscription when done.
        await uploadTask.onComplete;
        streamSubscription.cancel();

        String imageUrl = await storageReference.getDownloadURL();
        _imageUrls.add(imageUrl); //all all the urls to the list
      
      //upload the list of imageUrls to firebase as an array
      await _firestore.collection("users").document("user1").setData(
        "arrayOfImages": _imageUrls,
      );
     catch (e) 
      print(e);
    
  

您可以通过github project查看更多信息

【讨论】:

【参考方案3】:

您可以使用此方法将多个文件上传到 Firebase 存储,其中 List&lt;Asset&gt; 资产是您的 List&lt;File&gt; 文件。

Future<List<String>> uploadImage(
      @required String fileName, @required List<Asset> assets) async 
    List<String> uploadUrls = [];

    await Future.wait(assets.map((Asset asset) async 
      ByteData byteData = await asset.requestOriginal();
      List<int> imageData = byteData.buffer.asUint8List();

      StorageReference reference = FirebaseStorage.instance.ref().child(fileName);
      StorageUploadTask uploadTask = reference.putData(imageData);
      StorageTaskSnapshot storageTaskSnapshot;

      // Release the image data
      asset.releaseOriginal();

      StorageTaskSnapshot snapshot = await uploadTask.onComplete;
      if (snapshot.error == null) 
        storageTaskSnapshot = snapshot;
        final String downloadUrl = await storageTaskSnapshot.ref.getDownloadURL();
        uploadUrls.add(downloadUrl);

        print('Upload success');
       else 
        print('Error from image repo $snapshot.error.toString()');
        throw ('This file is not an image');
      
    ), eagerError: true, cleanUp: (_) 
     print('eager cleaned up');
    );

    return uploadUrls;

【讨论】:

如果你使用 multi_image_picker,asset.release 会被移除。引用插件 change_log “删除了 Asset.releaseThumb、Asset.releaseOriginal 和 Asset.release 方法,因为它们不再需要。” 我认为最好使用多个文件名【参考方案4】:

试试这个(在 onComplete 内):

storeRef.getDownloadURL() 

【讨论】:

以上是关于Flutter 上传一批图像并获取所有这些 URL 以存储在 Firestore 中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Cloud Function with Flutter 从新图像中获取 URL?

Flutter:获取 Firebase 存储下载 URL 和上传状态 [重复]

Flutter 无法上传从 multi_image_picker 获取的多张图片

http包在flutter中从api获取错误的图像url

Flutter将图像上传到firebase存储然后将其写入firestore

Flutter - 将图像上传到 Firebase 存储