📅  最后修改于: 2023-12-03 15:30:48.894000             🧑  作者: Mango
在 Flutter 开发中,我们经常需要从用户设备的存储中选择和打开文件。Flutter 提供了多种方法来处理此类任务,本篇文章将介绍其中的一些方法。
Flutter 提供了一个简单的 widget,可以启动设备的系统文件选择器,供用户选择和打开文件。
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
class FileSelectorPage extends StatefulWidget {
@override
_FileSelectorPageState createState() => _FileSelectorPageState();
}
class _FileSelectorPageState extends State<FileSelectorPage> {
File _selectedFile;
Future<void> _openFileSelector() async {
final result = await FilePicker.platform.pickFiles();
if (result != null) {
setState(() {
_selectedFile = File(result.files.first.path);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('文件选择器'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_selectedFile != null) ...[
Text('已选择:${_selectedFile.path}'),
SizedBox(height: 30),
RaisedButton(
child: Text('打开文件'),
onPressed: () async {
final bytes = await _selectedFile.readAsBytes();
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FileViewerPage(
bytes: bytes,
fileName: _selectedFile.path.split('/').last,
),
),
);
},
),
] else ...[
Text('未选择文件'),
],
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _openFileSelector,
),
);
}
}
class FileViewerPage extends StatefulWidget {
final List<int> bytes;
final String fileName;
FileViewerPage({@required this.bytes, @required this.fileName});
@override
_FileViewerPageState createState() => _FileViewerPageState();
}
class _FileViewerPageState extends State<FileViewerPage> {
Future<String> _getLocalPath() async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> _getLocalFile() async {
final path = await _getLocalPath();
return File('$path/${widget.fileName}');
}
Future<void> _writeFile() async {
final file = await _getLocalFile();
file.writeAsBytes(widget.bytes);
}
@override
void initState() {
super.initState();
_writeFile();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.fileName),
),
body: FutureBuilder(
future: _getLocalFile(),
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.hasData) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.file(snapshot.data),
],
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
代码分析:
整个应用程序分为两个页面:文件选择器页面和文件查看器页面。
在文件选择器页面中,我们使用 FilePicker.platform.pickFiles
方法来启动系统文件选择器。获取用户选择的文件之后,我们可以将其保存到 _selectedFile
变量中,并在页面上显示文件路径。
当用户点击“打开文件”按钮时,我们将选择的文件数据传递给文件查看器页面,并通过 Navigator
跳转到该页面。
在文件查看器页面中,我们首先需要将文件数据写入设备的本地存储中,以便在显示图片时使用。在 initState
方法中,我们调用 _writeFile
方法将文件数据写入本地文件。
在页面中,我们使用 FutureBuilder
读取本地文件,并通过 Image.file
显示图片。
需要注意的是,在 AndroidManifest.xml
文件中,我们需要添加以下权限声明:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
这些权限用于访问用户设备的外部存储。
通过本文的介绍,我们学习了在 Flutter 中如何使用系统文件选择器选择和打开文件,并从本地存储中读取文件数据。这些技术对于处理与文件相关的任务非常有用,例如文本编辑器、图像浏览器、音频/视频播放器等等。
完整代码片段请看文件中。