返回

利用Flutter应用下载文件

见解分享

正文

在Flutter中实现文件下载功能,可以让我们轻松构建出具有下载功能的应用,如文件管理器、音乐播放器、图片浏览器等。本文将介绍如何使用Flutter实现文件下载功能,涵盖从网络下载文件到保存到本地存储的完整流程。

1. 依赖引入

首先,我们需要在项目中引入必要的依赖库。打开项目中的pubspec.yaml文件,添加以下依赖:

dependencies:
  dio: ^4.0.0

2. 使用DIO库进行网络请求

DIO是一个功能强大的Flutter网络请求库,可以轻松地进行GET、POST、PUT、DELETE等各种类型的网络请求。

3. 创建下载任务

import 'dart:io';

import 'package:dio/dio.dart';

Future<void> downloadFile(String url, String savePath) async {
  try {
    // 创建DIO对象
    var dio = Dio();

    // 发起GET请求
    var response = await dio.get(
      url,
      options: Options(
        responseType: ResponseType.bytes,
        followRedirects: false,
        receiveTimeout: 0,
      ),
    );

    // 创建文件
    var file = File(savePath);

    // 将响应数据写入文件
    var raf = file.openSync(mode: FileMode.write);
    raf.writeFromSync(response.data);
    await raf.close();
  } catch (e) {
    print(e);
  }
}

4. 显示进度条

在下载过程中,我们可以使用进度条来显示下载进度。

import 'package:flutter/material.dart';

class DownloadProgress extends StatefulWidget {
  final double progress;

  const DownloadProgress({Key? key, required this.progress}) : super(key: key);

  @override
  State<DownloadProgress> createState() => _DownloadProgressState();
}

class _DownloadProgressState extends State<DownloadProgress> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 500));
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return LinearProgressIndicator(
          value: _controller.value,
        );
      },
    );
  }

  void updateProgress(double progress) {
    setState(() {
      _controller.value = progress;
    });
  }
}

5. 显示通知栏

在下载完成时,我们可以使用通知栏来提醒用户。

import 'package:flutter/material.dart';

void showNotification(String title, String body) {
  var androidNotificationDetails = const AndroidNotificationDetails(
    'channel_id',
    'channel_name',
    channelDescription: 'channel_description',
    importance: Importance.max,
    priority: Priority.high,
  );

  var iOSNotificationDetails = const IOSNotificationDetails(
    presentAlert: true,
    presentBadge: true,
    presentSound: true,
  );

  var notificationDetails = NotificationDetails(android: androidNotificationDetails, iOS: iOSNotificationDetails);

  var flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  flutterLocalNotificationsPlugin.show(0, title, body, notificationDetails);
}

6. 处理下载错误

在下载过程中,可能会遇到各种各样的错误,如网络错误、文件不存在错误等。

try {
  // 发起GET请求
  var response = await dio.get(
    url,
    options: Options(
      responseType: ResponseType.bytes,
      followRedirects: false,
      receiveTimeout: 0,
    ),
  );

  // 创建文件
  var file = File(savePath);

  // 将响应数据写入文件
  var raf = file.openSync(mode: FileMode.write);
  raf.writeFromSync(response.data);
  await raf.close();
} catch (e) {
  // 处理错误
  if (e is DioError) {
    switch (e.type) {
      case DioErrorType.connectTimeout:
        // 连接超时
        break;
      case DioErrorType.sendTimeout:
        // 发送超时
        break;
      case DioErrorType.receiveTimeout:
        // 接收超时
        break;
      case DioErrorType.response:
        // 服务器错误
        break;
      case DioErrorType.cancel:
        // 请求已取消
        break;
      case DioErrorType.other:
        // 其他错误
        break;
    }
  } else {
    // 其他类型的错误
  }
}

7. 使用示例

import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterDownloader.initialize();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('File Downloader'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              // 下载文件
              await downloadFile(
                'https://example.com/file.zip',
                '/storage/emulated/0/Download/file.zip',
              );

              // 显示通知栏
              showNotification('下载完成', '文件已下载到您的设备上。');
            },
            child: const Text('Download File'),
          ),
        ),
      ),
    );
  }
}