[译]Flutter文件选取器组件file_picker(一)使用指南

6,487 阅读3分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。

本文翻译自:

file_picker | Flutter Package (flutter-io.cn)

Installation · miguelpruivo/flutter_file_picker Wiki · GitHub

Setup · miguelpruivo/flutter_file_picker Wiki · GitHub

译时版本: file_picker 4.3.3


File Picker

允许使用原生文件浏览器选取单个或多个文件,支持扩展名过滤。

现在支持的特性

  • 使用操作系统默认的原生选取器
  • 支持多平台 (移动端、 Web 、 桌面端 和 go-flutter)
  • 使用自定义格式过滤器选取文件 - 你可以提供一个文件扩展名列表(pdf、 svg、 zip、等)。
  • 云文件选取 (GDrive、 Dropbox、 iCloud)
  • 选取单个或多个文件
  • 不同的默认类型的过滤器(多媒体、图像、视频、音频或其它任何类型)
  • 选取目录
  • 如果需要可直接将文件加载到内存 (Uint8List)中;
  • 打开一个 保存文件 / 另存为 对话框(对话框允许用户指定驱动器、目录和文件名来保存文件)

如果你想在该饮中看到某个特性,可自由提出建议。🎉

安装

将最新版本的 file_picker 依赖添加到 pubspec.yaml 文件中。

配置

Android

万事俱备,只要承认了运行时权限(包括插件),就准备好了!

也是不久之前,因为添加了对 Android 11 的兼容,你可能想要确认是在使用 可共存的 gradle 版本之一或者你可能会遇到编译问题,如 <query> 标签未被识别。

对于发布的编译,需要去掉 androidx.lifecycle.DefaultLifecycleObserver 防止混乱。可以在 android/app 文件夹下添加名为 proguard-rules.pro 的文件,并且加上以下规则:-keep class androidx.lifecycle.DefaultLifecycleObserver 来实现。

注意:  如果是在覆写 MainActivityonActivityResult,确保调用了 super.onActivityResult(...) 用于未处理的 activity 。否则选取文件会失败且没有任何错误信息。

iOS

由于 1.7.0 的子依赖, 需要添加 use_frameworks! 到 <project root>/ios/Podfile 中。

target 'Runner' do
  use_frameworks!

可选的权限

根据你想选取路径的文件的位置,可能需要添加一些 key 到 iOS 应用的 Info.plist 文件中,位于 <project root>/ios/Runner/Info.plist

  • UIBackgroundModes 带有 fetch 和 remote-notifications key - 如果要使用 FileType.any 或 FileType.custom ,该设置是必需的。描述应用需要访问后台任务的原因,例如下载文件(从云服务)。这称作 Required background modes (需要后台模式),在 IDE 中分别是 key App download content from network 和 App downloads content in response to push notifications (因为实际上两种方法没有被覆写,不添加这个 property/key ,不会显示警告,但是不应该阻止它的正确用法。)。

    <key>UIBackgroundModes</key>
    <array>
       <string>fetch</string>
       <string>remote-notification</string>
    </array>
    
  • NSAppleMusicUsageDescription - 如果要使用 FileType.audio , 该设置是必需的。描述应用需要音乐库权限的原因。在 IDE 中是 Privacy - Media Library Usage Description 。

    <key>NSAppleMusicUsageDescription</key>
    <string>Explain why your app uses music</string>
    
  • UISupportsDocumentBrowser - 如果要直接对目录进行写操作,该设置是必需的。通过这种方式,iOS 为应用和用户创建应用文件夹,用户在该文件夹中创建和选取目录,并且应用也有权限在此文件夹中进行写操作。

    <key>UISupportsDocumentBrowser</key>
    <true/>
    
  • LSSupportsOpeningDocumentsInPlace - 如果想要打开原始文件,而不是缓存文件(使用 FileType.all 时),该设置是必需的。

    <key>LSSupportsOpeningDocumentsInPlace</key>
    <true/>
    
  • NSPhotoLibraryUsageDescription - 如果在在使用 FileType.image 或 FileType.video 。描述应用需要相册权限的理由。在 IDE 中是 Privacy - Photo Library Usage Description 。

    <key>NSPhotoLibraryUsageDescription</key>
    <string>Explain why your app uses photo library</string>
    

注意:  低于 11.0 的任意 iOS 版本,会需要 Apple 开发者帐户使 CloudKit 可用,和使用文档选取器(当选取 FileType.all 、 FileType.custom 或者带  getMultiFilePath() 的其它任何选项)成为可能。可以在这里 了解更多内容。

Web

已安装 Flutter 2.0 或更高版本的话,就可以了。

桌面端

v4.0.0 开始该包支持所有的平台(Linux 、 macOS 和 Windows)。新的实现完全使用 Dart 编写。它代替了用 Go 编写需要 go-flutter 的旧实现。要在 macOS、 Linux 和 Windows 上使用,需要使桌面平台开发可用,取决于你想支持的操作系统:

$ flutter config --enable-windows-desktop
$ flutter config --enable-macos-desktop
$ flutter config --enable-linux-desktop

可以在这里了解更多内容。

桌面端(go-flutter)(不推荐)

此用法需要使用 Go 。 由于已不推荐,所以未翻译。

需要者可参考原文

用法

快速简单的用法示例:

单个文件

FilePickerResult? result = await FilePicker.platform.pickFiles();

if (result != null) {
  File file = File(result.files.single.path);
} else {
  // User canceled the picker
}

多个文件

FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true);

if (result != null) {
  List<File> files = result.paths.map((path) => File(path)).toList();
} else {
  // User canceled the picker
}

多个文件带扩展名过滤

FilePickerResult? result = await FilePicker.platform.pickFiles(
  type: FileType.custom,
  allowedExtensions: ['jpg', 'pdf', 'doc'],
);

选取目录

String? selectedDirectory = await FilePicker.platform.getDirectoryPath();

if (selectedDirectory == null) {
  // User canceled the picker
}

保存文件 / 另存为 对话框

String? outputFile = await FilePicker.platform.saveFile(
  dialogTitle: 'Please select an output file:',
  fileName: 'output-file.pdf',
);

if (outputFile == null) {
  // User canceled the picker
}

加载结果和文件详情

FilePickerResult? result = await FilePicker.platform.pickFiles();

if (result != null) {
  PlatformFile file = result.files.first;

  print(file.name);
  print(file.bytes);
  print(file.size);
  print(file.extension);
  print(file.path);
} else {
  // User canceled the picker
}

在 Flutter Web 上选取并上传一个文件到 Firebase 存储

FilePickerResult? result = await FilePicker.platform.pickFiles();

if (result != null) {
  Uint8List fileBytes = result.files.first.bytes;
  String fileName = result.files.first.name;
  
  // Upload file
  await FirebaseStorage.instance.ref('uploads/$fileName').putData(fileBytes);
}

完整的用法详细参考 Wiki 。

示例应用

flutter_file_picker/file_picker_demo.dart at master · miguelpruivo/flutter_file_picker · GitHub

Android

example.gif

iOS

example_ios.gif

MacOS

image.png

Linux

image.png

Windows

image.png