【问题标题】:Flutter web - Upload Image File to Firebase StorageFlutter web - 将图像文件上传到 Firebase 存储
【发布时间】:2020-04-30 04:27:02
【问题描述】:

在 Flutter Web 上,我从计算机中选择一个图像文件并获取一个 File 图像对象。然后我想把它上传到 Firebase Storage。对于应用程序的 Android 和 iOS 版本,我使用的是 Firebase Cloud Function 和 http 多部分请求。它有效,但对于应用程序的网络版本,它没有。所以,

如何将 html 图像文件直接或通过云函数上传到 Firebase 存储?

【问题讨论】:

标签: file-upload google-cloud-functions firebase-storage image-upload flutter-web


【解决方案1】:

最后我设法找到了解决这个问题的方法。为此,我需要安装两个依赖项,firebaseuniversal_html。 然而很难找到解决方案,它的实现实际上很简单。这是我用来将 html 图片文件上传到 Firebase Storage 的函数的代码,放到“images”文件夹中:

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?
  • @shinriyo 我遇到了同样的问题,文件已损坏。我该怎么办?
  • 你成就了我的一天!感谢您的回答
  • 这个答案,对我有用的是使用image_picker_for_web 来获取图像。然后将该图像转换为base64编码并使用putString而不是put,就像上面一样。更多关于 putString 的文档可以在here 找到
【解决方案2】:

这是对我有用的上传图片的完整片段: html.File 对我不起作用,文件已上传,但您会在 firebase 存储中看到 Error loading preview,所以直接传递字节对我有用。

要显示图像,您可以将mediaInfo.bytes 与支持字节的小部件一起使用,例如FadeInImage,您可以使用MemoryImage(mediaInfo.bytes)Image.memory(mediaInfo.bytes)

使用的包:

  1. firebase
  2. image_picker_web
  3. path
  4. mime_type
    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;
        }
      }

【讨论】:

    【解决方案3】:

    综合了这么多帖子后,我做到了,它成功了!

    不,您只是不需要任何种类的 Universal_HTML 或其他 image_picker_web。坚持使用 Image Picker(https://pub.dev/packages/image_picker)。 并使用下面的代码,就像我用来将图像上传到 Firebase 存储一样,它适用于 IOS、Android、Web 的所有方式,我希望你已经添加了 ios 和 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
    }
    
    }
    

    【讨论】:

      【解决方案4】:

      要在 Flutter for Web 应用程序中访问云存储,您可以使用 firebase-dart plugin。您可以在 repo 中找到accessing storage through firebase-dart 的示例。

      【解决方案5】:

      除了@WebRooseDevelopment,您可能还需要更新 index.html 文件以包含新的 firebase 版本。

      'src="https://www.gstatic.com/firebasejs/8.6.1/firebase-storage.js"&gt;'

      【讨论】:

      • (引用和装饰没有正确嵌套)
      【解决方案6】:
       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',
                                  ));
                            })
      

      【讨论】:

        【解决方案7】:

        相关附录:如何下载:为什么这是一个如此隐秘的秘密,我不知道。感谢Learn Flutter Code for this nice little tutorial.

        不要让 Firebase 存储成为依赖项,只需使用 Firebase:

        import 'package:firebase/firebase.dart' as fb;
        

        然后创建一个方法:

                Future<Uri> myDownloadURL() async {return await fb.storage().refFromURL('gs://<your storage reference>').child('$id.jpg').getDownloadURL();}
        

        像这样从 FutureBuilder 调用它:

                FutureBuilder<Uri>(
                future: myDownloadURL(),
                builder: (context, AsyncSnapshot<dynamic> snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return <Something as a placeholder>;
                  }
                  return CircleAvatar(
                    radius: backgroundRadius * 2,
                    child: Image.network(snapshot.data.toString()),
                  );
                },
              )
        

        【讨论】:

          猜你喜欢
          • 2021-08-11
          • 2021-07-03
          • 2021-07-28
          • 2018-10-24
          • 2019-01-22
          • 2020-12-20
          • 2021-03-29
          • 2021-09-19
          相关资源
          最近更新 更多