Flutter文件管理下载插件flutter_download_manager的使用
Flutter Download Manager
Overview
Flutter Download Manager is a Cross-Platform file downloader with Parallel and Batch Download support. Manage download tasks by URL and be notified of status and their progress. Pause, Cancel, Queue, and Resume Downloads.
Features
- Manage download tasks by URL
- Ability to be notified of status and progress changes
- Partial Download Feature
- Queue Downloads
- Pause, Cancel, or Resume Downloads
- Parallel File Downloads (2 or can change)
- Support Batch download
Platforms Supported
- Linux
- MacOS
- Windows
- Android
- iOS
Caveats
- On desktop, it saves the file in absolute or relative paths.
- On mobile, it saves the file in absolute or relative paths, but we should ask/ensure if the app has the required permissions.
- It does not run in a background process, so when the Dart application closes, the manager will also shut down.
Getting Started
In your pubspec.yaml
file, add:
dependencies:
flutter_download_manager: any
Then, in your code, import:
import 'package:flutter_download_manager/flutter_download_manager.dart';
Usage
Please refer to the /example
folder for a working example.
Simply Download a File
var dl = DownloadManager();
var url = "https://example.com/file.zip";
dl.addDownload(url, "./file.zip");
DownloadTask? task = dl.getDownload(url);
task?.status.addListener(() {
print(task.status.value);
});
task?.progress.addListener(() {
print(task.progress.value);
});
await dl.whenDownloadComplete(url);
Get Download Status
DownloadTask? task = dl.getDownload(url);
task?.status.addListener(() {
print(task.status.value);
});
Get Download Progress
DownloadTask? task = dl.getDownload(url);
task?.progress.addListener(() {
print(task.progress.value);
});
Await for a Task to Be Complete
DownloadTask? task = dl.getDownload(url);
await task.whenDownloadComplete();
Cancel a Task
var dl = DownloadManager();
dl.cancelDownload(url);
Pause a Task
var dl = DownloadManager();
dl.pauseDownload(url);
Resume a Task
var dl = DownloadManager();
dl.resumeDownload(url);
Download in Batch
var dl = DownloadManager();
var urls = <String>[];
urls.add(url1);
urls.add(url2);
urls.add(url3);
dl.addDownload(url1, "./file1.zip");
dl.addDownload(url2, "./file2.zip");
dl.addDownload(url3, "./file3.zip");
var downloadProgress = dl.getDownloadProgress(urls);
downloadProgress.addListener(() {
print(downloadProgress.value);
});
await dl.whenDownloadsComplete(urls);
Cancel a Batch Download
var dl = DownloadManager();
var urls = <String>[];
urls.add(url1);
urls.add(url2);
urls.add(url3);
dl.cancelDownloads(urls);
Get Batch Download Progress
var dl = DownloadManager();
var urls = <String>[];
urls.add(url1);
urls.add(url2);
var downloadProgress = dl.getDownloadProgress(urls);
downloadProgress.addListener(() {
print(downloadProgress.value);
});
Await for Batch Download to Complete
var dl = DownloadManager();
var urls = <String>[];
urls.add(url1);
urls.add(url2);
urls.add(url3);
await dl.whenDownloadsComplete(urls);
Future Work
- Add in Shared Preferences to survive app shutdown
DownloadStatus
enum DownloadStatus { queued, downloading, completed, failed, paused, canceled }
Example Code
Here is a complete example demonstrating how to use flutter_download_manager
in a Flutter application:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var url2 = "http://download.dcloud.net.cn/HBuilder.9.0.2.macosx_64.dmg";
var url3 = 'https://cdn.jsdelivr.net/gh/flutterchina/flutter-in-action@1.0/docs/imgs/book.jpg';
var url = "http://app01.78x56.com/Xii_2021-03-13%2010%EF%BC%9A41.ipa";
var url4 = "https://jsoncompare.org/LearningContainer/SampleFiles/Video/MP4/sample-mp4-file.mp4";
var url5 = "https://jsoncompare.org/LearningContainer/SampleFiles/Video/MP4/Sample-Video-File-For-Testing.mp4";
var downloadManager = DownloadManager();
var savedDir = "";
@override
void initState() {
super.initState();
getApplicationSupportDirectory().then((value) => savedDir = value.path);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Flutter Download Manager")),
body: SingleChildScrollView(
child: Column(
children: [
ListItem(
onDownloadPlayPausedPressed: (url) async {
setState(() {
var task = downloadManager.getDownload(url);
if (task != null && !task.status.value.isCompleted) {
switch (task.status.value) {
case DownloadStatus.downloading:
downloadManager.pauseDownload(url);
break;
case DownloadStatus.paused:
downloadManager.resumeDownload(url);
break;
}
} else {
downloadManager.addDownload(url,
"$savedDir/${downloadManager.getFileNameFromUrl(url)}");
}
});
},
onDelete: (url) {
var fileName = "$savedDir/${downloadManager.getFileNameFromUrl(url)}";
var file = File(fileName);
file.delete();
downloadManager.removeDownload(url);
setState(() {});
},
url: url,
downloadTask: downloadManager.getDownload(url)),
ListItem(
onDownloadPlayPausedPressed: (url) async {
setState(() {
var task = downloadManager.getDownload(url);
if (task != null && !task.status.value.isCompleted) {
switch (task.status.value) {
case DownloadStatus.downloading:
downloadManager.pauseDownload(url);
break;
case DownloadStatus.paused:
downloadManager.resumeDownload(url);
break;
}
} else {
downloadManager.addDownload(url,
"$savedDir/${downloadManager.getFileNameFromUrl(url)}");
}
});
},
onDelete: (url) {
var fileName = "$savedDir/${downloadManager.getFileNameFromUrl(url)}";
var file = File(fileName);
file.delete();
downloadManager.removeDownload(url);
setState(() {});
},
url: url2,
downloadTask: downloadManager.getDownload(url2)),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Batch Downloads"),
),
ListItem(
onDownloadPlayPausedPressed: (url) async {
setState(() {
var task = downloadManager.getDownload(url);
if (task != null && !task.status.value.isCompleted) {
switch (task.status.value) {
case DownloadStatus.downloading:
downloadManager.pauseDownload(url);
break;
case DownloadStatus.paused:
downloadManager.resumeDownload(url);
break;
}
} else {
downloadManager.addDownload(url,
"$savedDir/${downloadManager.getFileNameFromUrl(url)}");
}
});
},
onDelete: (url) {
var fileName = "$savedDir/${downloadManager.getFileNameFromUrl(url)}";
var file = File(fileName);
file.delete();
downloadManager.removeDownload(url);
setState(() {});
},
url: url3,
downloadTask: downloadManager.getDownload(url3)),
ListItem(
onDownloadPlayPausedPressed: (url) async {
setState(() {
var task = downloadManager.getDownload(url);
if (task != null && !task.status.value.isCompleted) {
switch (task.status.value) {
case DownloadStatus.downloading:
downloadManager.pauseDownload(url);
break;
case DownloadStatus.paused:
downloadManager.resumeDownload(url);
break;
}
} else {
downloadManager.addDownload(url,
"$savedDir/${downloadManager.getFileNameFromUrl(url)}");
}
});
},
onDelete: (url) {
var fileName = "$savedDir/${downloadManager.getFileNameFromUrl(url)}";
var file = File(fileName);
file.delete();
downloadManager.removeDownload(url);
setState(() {});
},
url: url4,
downloadTask: downloadManager.getDownload(url4)),
ListItem(
onDownloadPlayPausedPressed: (url) async {
setState(() {
var task = downloadManager.getDownload(url);
if (task != null && !task.status.value.isCompleted) {
switch (task.status.value) {
case DownloadStatus.downloading:
downloadManager.pauseDownload(url);
break;
case DownloadStatus.paused:
downloadManager.resumeDownload(url);
break;
}
} else {
downloadManager.addDownload(url,
"$savedDir/${downloadManager.getFileNameFromUrl(url)}");
}
});
},
onDelete: (url) {
var fileName = "$savedDir/${downloadManager.getFileNameFromUrl(url)}";
var file = File(fileName);
file.delete();
downloadManager.removeDownload(url);
setState(() {});
},
url: url5,
downloadTask: downloadManager.getDownload(url5)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {
downloadManager.addBatchDownloads(
[url3, url4, url5], savedDir);
setState(() {});
},
child: Text("Download All")),
TextButton(
onPressed: () {
downloadManager.pauseBatchDownloads([url3, url4, url5]);
},
child: Text("Pause All")),
TextButton(
onPressed: () {
downloadManager.cancelBatchDownloads([url3, url4, url5]);
},
child: Text("Cancel All")),
],
),
ValueListenableBuilder(
valueListenable: downloadManager
.getBatchDownloadProgress([url3, url4, url5]),
builder: (context, value, child) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 4),
child: LinearProgressIndicator(
value: value,
),
);
}),
FutureBuilder<List<DownloadTask?>?>(
future: downloadManager
.whenBatchDownloadsComplete([url3, url4, url5]),
builder: (BuildContext context,
AsyncSnapshot<List<DownloadTask?>?> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text(
'I will wait till the batch downloads have been completed');
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return snapshot.data != null
? Column(children: [
Text("Result"),
for (var e in snapshot.data!)
e != null
? Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
"${downloadManager.getFileNameFromUrl(e.request.url)}: ${e.status.value}"),
)
: Text("Not found"),
])
: Text("No Downloads have been found");
}
}
})
],
),
)
],
),
),
);
}
}
class ListItem extends StatelessWidget {
final Function(String) onDownloadPlayPausedPressed;
final Function(String) onDelete;
DownloadTask? downloadTask;
String url = "";
ListItem({
Key? key,
required this.url,
required this.onDownloadPlayPausedPressed,
required this.onDelete,
this.downloadTask,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.amber,
),
borderRadius: BorderRadius.all(Radius.circular(20))),
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
url,
overflow: TextOverflow.ellipsis,
),
if (downloadTask != null)
ValueListenableBuilder(
valueListenable: downloadTask!.status,
builder: (context, value, child) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Text("$value",
style: TextStyle(fontSize: 16)),
);
}),
],
)),
downloadTask != null
? ValueListenableBuilder(
valueListenable: downloadTask!.status,
builder: (context, value, child) {
switch (downloadTask!.status.value) {
case DownloadStatus.downloading:
return IconButton(
onPressed: () {
onDownloadPlayPausedPressed(url);
},
icon: const Icon(Icons.pause));
case DownloadStatus.paused:
return IconButton(
onPressed: () {
onDownloadPlayPausedPressed(url);
},
icon: const Icon(Icons.play_arrow));
case DownloadStatus.completed:
return IconButton(
onPressed: () {
onDelete(url);
},
icon: const Icon(Icons.delete));
case DownloadStatus.failed:
case DownloadStatus.canceled:
return IconButton(
onPressed: () {
onDownloadPlayPausedPressed(url);
},
icon: const Icon(Icons.download));
}
return Text("$value", style: TextStyle(fontSize: 16));
})
: IconButton(
onPressed: () {
onDownloadPlayPausedPressed(url);
},
icon: const Icon(Icons.download))
],
),
if (downloadTask != null && !downloadTask!.status.value.isCompleted)
ValueListenableBuilder(
valueListenable: downloadTask!.progress,
builder: (context, value, child) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 4),
child: LinearProgressIndicator(
value: value,
color: downloadTask!.status.value == DownloadStatus.paused
? Colors.grey
: Colors.amber,
),
);
}),
if (downloadTask != null)
FutureBuilder<DownloadStatus>(
future: downloadTask!.whenDownloadComplete(),
builder: (BuildContext context,
AsyncSnapshot<DownloadStatus> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text(
'I will wait till this download has been completed');
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text('Result: ${snapshot.data}');
}
}
})
],
),
),
);
}
}
This example demonstrates how to manage individual and batch downloads, including starting, pausing, resuming, and canceling downloads. It also shows how to display the download status and progress in a user interface.
更多关于Flutter文件管理下载插件flutter_download_manager的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter文件管理下载插件flutter_download_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 flutter_download_manager
插件在 Flutter 中进行文件下载和管理的代码示例。这个插件允许你在 Flutter 应用中下载文件,并跟踪下载进度和状态。
首先,确保你已经在 pubspec.yaml
文件中添加了 flutter_download_manager
依赖:
dependencies:
flutter:
sdk: flutter
flutter_download_manager: ^x.y.z # 请将 x.y.z 替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
接下来,是示例代码,展示如何使用 flutter_download_manager
:
1. 初始化下载管理器
在你的应用主文件(通常是 main.dart
)中,初始化下载管理器。
import 'package:flutter/material.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化下载管理器
configureDownloadManager();
runApp(MyApp());
}
void configureDownloadManager() {
// 设置下载目录(可选)
DownloadConfig.init(
debug: true, // 如果需要日志输出,设置为 true
defaultSaveDir: DownloadConfig.APPLICATION_DOCUMENTS_DIR // 或者其他目录
).then((_) {
// 初始化完成
print("Download Manager Configured");
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
2. 创建一个下载按钮
在你的 HomeScreen
中,添加一个按钮来触发下载。
import 'package:flutter/material.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<DownloadTask> downloads = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Download Manager Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => startDownload(),
child: Text('Start Download'),
),
Expanded(
child: ListView.builder(
itemCount: downloads.length,
itemBuilder: (context, index) {
DownloadTask task = downloads[index];
return ListTile(
title: Text('Download ID: ${task.taskId}'),
subtitle: Text('Status: ${task.status.toString()}'),
trailing: Icon(
Icons.file_download,
color: task.status == DownloadStatus.COMPLETED
? Colors.green
: Colors.red,
),
);
},
),
),
],
),
),
);
}
void startDownload() async {
String url = 'https://example.com/path/to/your/file.zip';
String fileName = 'file.zip';
try {
DownloadTask task = await FlutterDownloadManager.instance.start(
taskId: DateTime.now().toString(),
url: url,
savedDir: DownloadConfig.APPLICATION_DOCUMENTS_DIR,
fileName: fileName,
headers: {"Authorization": "Bearer YOUR_TOKEN"}, // 可选,如果需要添加请求头
showNotification: true, // 是否在下载完成时显示通知
openFileFromNotification: true, // 是否从通知中打开文件
);
// 将任务添加到列表中
setState(() {
downloads.add(task);
});
// 监听下载进度
task.progress.listen((progress) {
print('Download progress: ${progress.progressInPercent}%');
});
// 监听下载状态
task.status.listen((status) {
print('Download status: $status');
// 更新 UI 或执行其他操作
setState(() {});
});
} catch (e) {
print('Download failed: $e');
}
}
}
3. 权限处理
不要忘记在 Android 和 iOS 上处理必要的权限,尤其是存储权限。对于 Android,你需要在 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"/>
并在运行时请求权限(如果需要)。
对于 iOS,确保在 Info.plist
中添加适当的权限描述。
注意事项
- 确保在测试时网络连接正常。
- 根据需要调整下载目录和文件名。
- 处理错误和异常,确保用户体验良好。
这个示例展示了如何使用 flutter_download_manager
插件进行文件下载和基本的进度与状态管理。你可以根据需要进一步扩展和自定义。