Flutter: carga y descarga de archivos (vista previa después de la descarga)

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.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

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 DownloadTaskdevolverá una tarea, se pueden usar varias tareas downloadBatchpara 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_notificationspara implementar la función de notificación
Flutter: flutter_local_notifications - learning of message push
inserte la descripción de la imagen aquí

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 se mp4puede abrir directamente después de que se complete la descarga, pero zipdicho 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

inserte la descripción de la imagen aquí
Esto se debe a que background_downloaderla versión mínima requerida de sdk es 24, y Flutter la establecerá automáticamente minSdkVersionen 16 (Android 4.1), en android/app/build.gradlelos archivos de su proyecto Flutter, minSdkVersioncambiará a 24 o superior. Luego ejecute flutter cleanun proyecto limpio y reconstruya su aplicación.
inserte la descripción de la imagen aquí
La solución a este problema se encontró en el repositorio de flutter: https://github.com/flutter/flutter/issues/119247

en android / app/build.gradleel archivo agregar

configurations.all {
    
    
    resolutionStrategy {
    
    
        eachDependency {
    
    
            if ((requested.group == "org.jetbrains.kotlin") && (requested.name.startsWith("kotlin-stdlib"))) {
    
    
                useVersion("1.8.0")
            }
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_41897680/article/details/132184029
Recomendado
Clasificación