Flutter文件下载管理插件fl_downloader的使用
Flutter文件下载管理插件fl_downloader的使用
插件介绍
fl_downloader
是一个用于Flutter应用程序的插件,它允许您通过原生功能下载文件。在Android上,它使用系统的DownloadManager
服务;在Windows上,它使用BITS(Background Intelligent Transfer Service)将文件下载到用户的Downloads文件夹中;在iOS上,它使用URLSession
将文件下载到App Documents文件夹。
iOS配置
如果您不想让用户在Files应用中看到已下载的文件,则无需特殊配置。
如果希望用户能在Files应用中查看已下载的文件,请在您的info.plist
文件中添加以下行:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
Android配置
对于Android 10+,无需特殊配置。
如果您的应用支持Android 9(API 28)或更低版本,在调用download()
之前必须调用requestPermission()
并检查权限状态。
注意:此插件期望compileSdk
是最新版本的Android SDK,例如:
android {
compileSdk 34
[...]
}
Windows配置
Windows平台无需特殊配置。
需要注意的是,了解BITS的限制和测试其使用情况非常重要,相关文档如下:
示例代码
下面是一个完整的示例demo,展示了如何使用fl_downloader
插件进行文件下载,并实时更新下载进度、处理不同状态等。
import 'dart:async';
import 'package:fl_downloader/fl_downloader.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController fileNameController = TextEditingController(
text: 'test.pdf',
);
final TextEditingController urlController = TextEditingController(
text:
'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
);
int progress = 0;
dynamic downloadId;
String? status;
late StreamSubscription progressStream;
@override
void initState() {
FlDownloader.initialize();
progressStream = FlDownloader.progressStream.listen((event) {
if (event.status == DownloadStatus.successful) {
debugPrint('event.progress: ${event.progress}');
setState(() {
progress = event.progress;
downloadId = event.downloadId;
status = event.status.name;
});
// 自动打开下载完成后的文件
FlDownloader.openFile(filePath: event.filePath);
} else if (event.status == DownloadStatus.running) {
debugPrint('event.progress: ${event.progress}');
setState(() {
progress = event.progress;
downloadId = event.downloadId;
status = event.status.name;
});
} else if (event.status == DownloadStatus.failed) {
debugPrint('event: $event');
setState(() {
progress = event.progress;
downloadId = event.downloadId;
status = event.status.name;
});
} else if (event.status == DownloadStatus.paused) {
debugPrint('Download paused');
setState(() {
progress = event.progress;
downloadId = event.downloadId;
status = event.status.name;
});
// 在暂停后重新附加下载进度
Future.delayed(
const Duration(milliseconds: 250),
() => FlDownloader.attachDownloadProgress(event.downloadId),
);
} else if (event.status == DownloadStatus.pending) {
debugPrint('Download pending');
setState(() {
progress = event.progress;
downloadId = event.downloadId;
status = event.status.name;
});
}
});
super.initState();
}
@override
void dispose() {
progressStream.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
home: Scaffold(
appBar: AppBar(
title: const Text('FlDownloader example app'),
),
body: Column(
children: [
if (progress > 0 && progress < 100)
LinearProgressIndicator(
value: progress / 100,
color: Colors.orange,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: TextField(
controller: urlController,
decoration: const InputDecoration(
label: Text('URL'),
border: OutlineInputBorder(),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: TextField(
controller: fileNameController,
decoration: const InputDecoration(
label: Text('File name'),
border: OutlineInputBorder(),
),
),
),
const Spacer(),
Text(
'Download id: $downloadId\n'
'Status: $status\n'
'Progress: $progress%',
),
const Spacer(),
],
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
backgroundColor: Colors.red[300],
child: const Icon(Icons.close),
onPressed: () async {
final cancelList = [downloadId];
final cancelled = await FlDownloader.cancel(cancelList);
if (cancelled == cancelList.length) {
setState(() {
progress = 0;
downloadId = null;
status = 'All downloads cancelled';
});
} else {
setState(() {
progress = 0;
downloadId = null;
status = 'Cancelled $cancelled downloads from the list';
});
}
},
),
const SizedBox(width: 10),
FloatingActionButton(
child: const Icon(Icons.download_sharp),
onPressed: () async {
final permission = await FlDownloader.requestPermission();
if (permission == StoragePermissionStatus.granted) {
await FlDownloader.download(
urlController.text,
fileName: fileNameController.text,
);
} else {
debugPrint('Permission denied =(');
}
},
),
],
),
),
);
}
}
这个示例提供了一个简单的界面,允许用户输入文件的URL和名称,然后点击按钮开始下载。同时,它还显示了下载进度条以及当前的下载状态。当下载完成后,会尝试自动打开下载的文件。此外,也提供了取消下载的功能。
更多关于Flutter文件下载管理插件fl_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter文件下载管理插件fl_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用fl_downloader
插件进行文件下载管理的代码示例。fl_downloader
是一个强大的Flutter插件,用于在后台处理文件下载任务,并提供下载进度的回调。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加fl_downloader
依赖:
dependencies:
flutter:
sdk: flutter
fl_downloader: ^2.0.3 # 确保使用最新版本
然后运行flutter pub get
来安装依赖。
2. 配置Android和iOS
Android
在android/app/src/main/AndroidManifest.xml
中添加以下权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
并配置FlutterDownloader
服务:
<service
android:name="vn.hunghd.flutterdownloader.FlutterDownloaderService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaProjection"/>
iOS
在ios/Runner/Info.plist
中添加以下权限:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
3. 初始化插件
在你的Flutter项目的入口文件(通常是main.dart
)中初始化FlutterDownloader
:
import 'package:flutter/material.dart';
import 'package:fl_downloader/fl_downloader.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
FlutterDownloader.initialize(
debug: true // 开启调试模式(生产环境建议关闭)
).then((value) {
runApp(MyApp());
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
4. 开始下载
在你的下载页面(如HomePage.dart
)中添加下载功能:
import 'package:flutter/material.dart';
import 'package:fl_downloader/fl_downloader.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final String taskId = "task_id_123";
String downloadUrl = "https://example.com/yourfile.zip";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("File Downloader"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
startDownload();
},
child: Text("Start Download"),
),
),
);
}
void startDownload() async {
final Task task = FlutterDownloader.enqueue(
taskId: taskId,
url: downloadUrl,
savedDir: "${FlutterDownloader.defaultStorageDir}/downloads/",
showNotification: true,
openFileFromNotification: true,
);
task.listen(
(id, status, progress) {
if (status == TaskStatus.completed) {
print("Download completed: $id");
} else if (status == TaskStatus.running) {
print("Download running: $progress");
} else {
print("Download failed: $status");
}
},
onError: (id, error, exception) => print("Download error: $error"),
);
}
}
5. 处理下载完成后的文件
当用户点击通知栏的下载完成时,fl_downloader
会自动打开文件。如果你想在下载完成后进行其他操作,可以监听task.listen
中的TaskStatus.completed
状态。
6. 清理和取消下载
你可以使用FlutterDownloader.cancel(taskId: taskId)
来取消下载任务,或者使用FlutterDownloader.clean(taskId: taskId)
来清理下载任务及其文件。
总结
以上是如何在Flutter项目中使用fl_downloader
插件进行文件下载管理的完整示例。这个插件提供了强大的后台下载功能,并支持下载进度监听和通知栏显示。希望这个示例能够帮助你快速上手fl_downloader
的使用。