【问题标题】:如何使用 Flutter Web 选择要上传的文件和图像
【发布时间】:2019-10-08 16:59:33
【问题描述】:

我想知道如何从用户计算机中选择一张图片到我的 Flutter Web 应用中进行上传

【问题讨论】:

  • 您可以在另一篇文章中查看我的答案here。它基本上使用来自dart:html 包的FileUploadInputElement

标签: dart flutter flutter-web


【解决方案1】:

我尝试了下面的代码,它成功了。

第一个import 'dart:html';

// variable to hold image to be displayed 

      Uint8List uploadedImage;

//method to load image and update `uploadedImage`


    _startFilePicker() async {
    InputElement uploadInput = FileUploadInputElement();
    uploadInput.click();

    uploadInput.onChange.listen((e) {
      // read file content as dataURL
      final files = uploadInput.files;
      if (files.length == 1) {
        final file = files[0];
        FileReader reader =  FileReader();

        reader.onLoadEnd.listen((e) {
                    setState(() {
                      uploadedImage = reader.result;
                    });
        });

        reader.onError.listen((fileEvent) {
          setState(() {
            option1Text = "Some Error occured while reading the file";
          });
        });

        reader.readAsArrayBuffer(file);
      }
    });
    }

现在只是任何 Widget,比如一个按钮并调用方法 _startFilePicker()

【讨论】:

  • 有没有办法检测文件选择器是否被取消?
  • @AbdulRafay 我对 Web 的理解没有任何取消的回调。
  • 我发现使用颤振网络上传图像非常困难。这个解决方案也给出了错误 - : - 有人知道为什么吗?
【解决方案2】:

接受的答案已经过时,不建议直接在Flutter中使用dart:html包。

改为使用这个包:https://pub.dev/packages/file_picker

如何在 Flutter Web 中使用示例:

class FileUploadButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      child: Text('UPLOAD FILE'),
      onPressed: () async {
        var picked = await FilePicker.platform.pickFiles();

        if (picked != null) {
          print(picked.files.first.name);
        }
      },
    );
  }
}

请注意,Flutter Web 不支持 FilePickerResult.path

【讨论】:

  • 我正在使用此依赖项但没有获取路径。我必须将其上传到 firebase 。那么flutter web用什么来选择web的文件路径
  • 这在flutter web中有效,但不需要路径,也没有实现,如文档中的explicitly所述。只需使用 PlatformFile.bytes 属性来访问字节。
  • 为什么我总是在 .bytes 上得到空值?
  • 多部分请求需要一个 Stream>。如何从 .bytes 中得到这个?
  • ByteStream.fromBytes(bytes!.toList())
【解决方案3】:
import 'package:http/http.dart' as http;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';

class FileUploadWithHttp extends StatefulWidget {
  @override
  _FileUploadWithHttpState createState() => _FileUploadWithHttpState();
}

class _FileUploadWithHttpState extends State<FileUploadWithHttp> {
  PlatformFile objFile = null;

  void chooseFileUsingFilePicker() async {
    //-----pick file by file picker,

    var result = await FilePicker.platform.pickFiles(
      withReadStream:
          true, // this will return PlatformFile object with read stream
    );
    if (result != null) {
      setState(() {
        objFile = result.files.single;
      });
    }
  }

  void uploadSelectedFile() async {
    //---Create http package multipart request object
    final request = http.MultipartRequest(
      "POST",
      Uri.parse("Your API URL"),
    );
    //-----add other fields if needed
    request.fields["id"] = "abc";

    //-----add selected file with request
    request.files.add(new http.MultipartFile(
        "Your parameter name on server side", objFile.readStream, objFile.size,
        filename: objFile.name));

    //-------Send request
    var resp = await request.send();

    //------Read response
    String result = await resp.stream.bytesToString();

    //-------Your response
    print(result);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          //------Button to choose file using file picker plugin
          RaisedButton(
              child: Text("Choose File"),
              onPressed: () => chooseFileUsingFilePicker()),
          //------Show file name when file is selected
          if (objFile != null) Text("File name : ${objFile.name}"),
          //------Show file size when file is selected
          if (objFile != null) Text("File size : ${objFile.size} bytes"),
          //------Show upload utton when file is selected
          RaisedButton(
              child: Text("Upload"), onPressed: () => uploadSelectedFile()),
        ],
      ),
    );
  }
}

【讨论】:

  • 请添加有关您的答案的更多详细信息
  • 我们可以用它来做flutter web吗
  • @RahulKushwaha 是的!它在 Flutter Web 中运行良好。
  • @LadKhushbu 选择任何 .docs 文件时,它给了我 null aas 路径。我正在使用 pub.dev/packages/file_picker 包。
  • @RahulKushwaha 是的,它会在网络中返回空路径,所以使用 ReadStream 上传文件。
【解决方案4】:

我已经测试了这个包并且对结果非常满意imagePickerWeb 它返回了 3 种不同的类型,可以是图像(预览小部件)、字节、文件(上传)的形式

然后你可以使用它来获取值

html.File _cloudFile;
 var _fileBytes;
 Image _imageWidget;
 
 Future<void> getMultipleImageInfos() async {
    var mediaData = await ImagePickerWeb.getImageInfo;
    String mimeType = mime(Path.basename(mediaData.fileName));
    html.File mediaFile =
        new html.File(mediaData.data, mediaData.fileName, {'type': mimeType});

    if (mediaFile != null) {
      setState(() {
        _cloudFile = mediaFile;
        _fileBytes = mediaData.data;
        _imageWidget = Image.memory(mediaData.data);
      });
    }

上传到 Firebase

别忘了把它添加到你的 index.html 中

  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-storage.js"></script>

上传到 Firebase

import 'package:firebase/firebase.dart' as fb;
    uploadToFirebase(File file) async {

    final filePath = 'temp/${DateTime.now()}.png';//path to save Storage
    try {
      fb
          .storage()
          .refFromURL('urlFromStorage')
          .child(filePath)
          .put(file);
    } catch (e) {
      print('error:$e');
    }
  }

如果仍有问题,请参阅包的文档

【讨论】:

【解决方案5】:

接受的答案确实已经过时了。就像 jnt 建议的那样,https://pub.dev/packages/file_picker 是一个方便的包,用于使用 Flutter Web 实现图像上传。

我面临的问题是获取图像的 base64 表示,因为我使用它在 Firestore 中存储图像。正如我们所知,Flutter Web 不支持 dart:io 并抛出 Unsupported operation: _Namespace 错误。因此,使用File 并读取文件的字节不是一种选择。幸运的是,该包提供了将上传的图像转换为Uint8List 的 API。这是我的实现:

import 'package:file_picker/file_picker.dart';

...

FilePickerResult? pickedFile;

...

void chooseImage() async {
    pickedFile = await FilePicker.platform.pickFiles();
    if (pickedFile != null) {
      try {
        setState(() {
          logoBase64 = pickedFile!.files.first.bytes;
        });
      } catch (err) {
        print(err);
      }
    } else {
      print('No Image Selected');
    }
}

如果您需要立即显示本地图像,请使用Image.memory

Image.memory(logoBase64!);

【讨论】:

    【解决方案6】:

    我也有这个问题;

    我使用https://pub.dev/packages/file_picker,但在颤动的网络路径中不支持;

    你应该使用字节;

    我将文件字节保存在 var _fileBytes 中并在请求中使用;

    var request = http.MultipartRequest('POST', Uri.parse('https://.....com'));
    request.headers.addAll(headers);
    request.files.add(
       http.MultipartFile.fromBytes(
         'image', 
          await ConvertFileToCast(_fileBytes),
          filename: fileName,
          contentType: MediaType('*', '*')
       )
    );
    request.fields.addAll(fields);
    var response = await request.send();
    

    函数 ConvertFileToCast:

    ConvertFileToCast(data){
      List<int> list = data.cast();
      return list;
    }
    

    这对我有用:)

    【讨论】:

      猜你喜欢
      • 2021-11-11
      • 2019-12-07
      • 2021-10-29
      • 2020-05-05
      • 2020-04-15
      • 2020-02-23
      • 2021-08-26
      • 2020-11-28
      • 2020-08-13
      相关资源
      最近更新 更多