dio
dio es una poderosa biblioteca de solicitudes de Dart Http, que proporciona funciones ricas y una API fácil de usar, y admite la carga y descarga de archivos.
Esto no se presentará, hay muchos casos de encapsulación en Internet.
fondo_descargador
Introducción
Descarga y carga de archivos en segundo plano para iOS, Android, MacOS, Windows y Linux.
Documento oficial
https://pub-web.flutter-io.cn/packages/background_downloader
Instalar
flutter pub add background_downloader
Ejemplo 1: Descargar
class _MyHomePageState extends State<MyHomePage> {
// 文件信息
String fileInfo = '';
// 下载进度
double progress = 0.0;
// 任务状态
String taskStatus = '';
// 任务
late DownloadTask task;
// 下载单个文件
_downloadFile() async {
task = DownloadTask(
url:
'https://vd3.bdstatic.com/mda-ma6igm4b0znfbqve/sc/cae_h264_nowatermark/1609998111/mda-ma6igm4b0znfbqve.mp4', // 下载地址
// urlQueryParameters: {'q': 'pizza'}, // 请求参数
filename: 'mov_bbb.mp4', // 文件名
//headers: {'myHeader': 'value'}, 请求头
directory: 'my_sub_directory', // 文件存储目录
updates: Updates.statusAndProgress, // 更新任务状态和下载进度
requiresWiFi: true, // 使用wifi
retries: 5, // 下载的重试次数
allowPause: true, // 运行暂停
metaData: 'data for me' // 元数据,可以存储一些对于下载任务有用的信息,方便后续相关操作
);
// 监听下载
final result =
await FileDownloader().download(task, onProgress: (progress) {
setState(() {
this.progress = progress;
});
}, onStatus: (states) {
String msg = '';
if (states == TaskStatus.complete) {
msg = '下载完成';
// 下载完成后,将文件移动到共享目录后,其他应用也可以访问。否则只能在本应用内访问
FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
} else if (states == TaskStatus.canceled) {
msg = '已取消';
setState(() {
progress = 0;
});
} else if (states == TaskStatus.paused) {
msg = '已暂停';
} else if (states == TaskStatus.running) {
msg = '下载中...';
} else {
msg = '下载失败';
}
setState(() {
taskStatus = msg;
});
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Column(
children: [
const SizedBox(
height: 20,
),
Text("文件信息:$fileInfo"),
const SizedBox(
height: 20,
),
Row(
children: [
const Text("下载进度:"),
Expanded(
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.greenAccent,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.red),
)),
Text("${
(progress * 100).toStringAsFixed(1)}%")
],
),
Text("任务状态:$taskStatus"),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: [
ElevatedButton(
onPressed: _downloadFile, child: const Text("下载")),
ElevatedButton(
onPressed: () async {
// 暂停任务
await FileDownloader().pause(task);
},
child: const Text("暂停")),
ElevatedButton(
onPressed: () async {
// 根据固定的任务id取消
await FileDownloader().cancelTaskWithId(task.taskId);
// 取消所有
//FileDownloader().cancelTasksWithIds(taskIds)
},
child: const Text("取消")),
ElevatedButton(
onPressed: () async {
await FileDownloader().resume(task);
},
child: const Text("恢复"))
],
)
],
));
}
}
Aviso:
- Los archivos descargados por defecto están en esta aplicación, y otras aplicaciones no tienen derechos de acceso. Para acceder, debe ejecutarse después de que se complete la descarga
FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
- Después de hacer clic en Pausa, haga clic en Reanudar para reanudar la descarga. Después de hacer clic en Cancelar, haga clic en Reanudar para continuar con la descarga.
Ejemplo 2: Subir
/// define the multi-part upload task (subset of parameters shown)
final task = UploadTask(
url: 'https://myserver.com/uploads',
filename: 'myData.txt',
fields: {
'datafield': 'value'},
fileField: 'myFile',
updates: Updates.statusAndProgress // request status and progress updates
);
// Start upload, and wait for result. Show progress and status changes
// while uploading
final result = await FileDownloader().upload(task,
onProgress: (progress) => print('Progress: ${
progress * 100}%'),
onStatus: (status) => print('Status: $status')
);
// Act on result, similar to download
Este no tiene un servidor, no lo probé, el anterior es el ejemplo oficial.
Ejemplo 3: Descarga por lotes
final tasks = [task1, task2, task3]; // a list of Download tasks
// download the batch
final result = await FileDownloader().downloadBatch(tasks,
batchProgressCallback: (succeeded, failed) =>
print('Completed ${
succeeded + failed} out of ${
tasks.length}, $failed failed')
);
El uso DownloadTask
devolverá una tarea, se pueden usar varias tareas downloadBatch
para la descarga por lotes.
Ejemplo 4: Iniciar una notificación
Lo probé según el ejemplo oficial, pero no se inició ninguna notificación.
Mi problema aquí es que la aplicación no tiene permisos de notificación y las notificaciones no se pueden activar en la configuración.
Si no tiene éxito, puede utilizar flutter_local_notifications
para implementar la función de notificación
Flutter: flutter_local_notifications - learning of message push
Ejemplo 5: Abrir un archivo descargado
_downloadFile() async {
task = DownloadTask(
url:
'https://ppt.1ppt.com/uploads/soft/2307/1-230H1092638.zip', // 下载地址
// urlQueryParameters: {'q': 'pizza'}, // 请求参数
filename: '1-230H1092638.zip', // 文件名
//headers: {'myHeader': 'value'}, 请求头
directory: 'my_sub_directory', // 文件存储目录
baseDirectory: BaseDirectory.applicationSupport,
updates: Updates.statusAndProgress, // 更新任务状态和下载进度
requiresWiFi: true, // 使用wifi
retries: 5, // 下载的重试次数
allowPause: true, // 运行暂停
metaData: 'data for me' // 元数据,可以存储一些对于下载任务有用的信息,方便后续相关操作
);
// 监听下载
final result =
await FileDownloader().download(task, onProgress: (progress) {
setState(() {
this.progress = progress;
});
}, onStatus: (states) async{
String msg = '';
if (states == TaskStatus.complete) {
msg = '下载完成';
await FileDownloader().openFile(task: task);
print("路径:${
await task.filePath()}");
} else if (states == TaskStatus.canceled) {
msg = '已取消';
setState(() {
progress = 0;
});
} else if (states == TaskStatus.paused) {
msg = '已暂停';
} else if (states == TaskStatus.running) {
msg = '下载中...';
} else {
msg = '下载失败';
}
setState(() {
taskStatus = msg;
});
});
}
Aviso:
- Se debe agregar
baseDirectory: BaseDirectory.applicationSupport,
, de lo contrario, el archivo no se puede abrir - Si desea abrir el archivo, no puede usar
FileDownloader().moveToSharedStorage(task, SharedStorage.downloads);
el archivo de movimiento, lo que hará que el archivo no se encuentre y luego no se abra. Además, al abrir el archivo, llamará a la aplicación en su teléfono móvil para abrirlo. Probé la imagen y semp4
puede abrir directamente después de que se complete la descarga, perozip
dicho archivo no se puede abrir directamente. En este momento, se le pedirá que elija la aplicación de su teléfono móvil para abrirla.
problemas encontrados
Esto se debe a que background_downloader
la versión mínima requerida de sdk es 24, y Flutter la establecerá automáticamente minSdkVersion
en 16 (Android 4.1), en android/app/build.gradle
los archivos de su proyecto Flutter, minSdkVersion
cambiará a 24 o superior. Luego ejecute flutter clean
un proyecto limpio y reconstruya su aplicación.
La solución a este problema se encontró en el repositorio de flutter: https://github.com/flutter/flutter/issues/119247
en android / app/build.gradle
el archivo agregar
configurations.all {
resolutionStrategy {
eachDependency {
if ((requested.group == "org.jetbrains.kotlin") && (requested.name.startsWith("kotlin-stdlib"))) {
useVersion("1.8.0")
}
}
}
}