controller.dart 4.2 KB
/*
 * @Author: 卢靖康
 * @Date: 2024-04-24 18:50:26
 * @LastEditTime: 2024-05-06 15:21:58
 * @LastEditors: 卢靖康
 */
import 'dart:convert';
import 'dart:io';

import 'package:archive/archive.dart';
import 'package:archive/archive_io.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'model.dart';

class DownloadController extends GetxController {
  DownloadController();

  List<DownloadItemModel> downloadFileList = [
    DownloadItemModel(
        id: 1,
        name: "地图1",
        path: 'http://seaworldmap.shleads.com/dist.zip',
        fileName: 'dist.zip',
        isDownload: false,
        progress: 0.0,
        savePath: '',
        zipFiles: []),
  ];

  _initData() async {
    update(["download"]);
  }

  handleDownload(item) async {
    if (item.isDownload) {
      return;
    } else {
      Get.snackbar('提示', '正在下载');
    }
    Directory dir = await localfileDir();
    String path = dir.path;
    String fileName = item.fileName;
    String saveDirectoryPath = "$path/download/$fileName";
    print(saveDirectoryPath);

    Dio dio = Dio();

    try {
      dio.download(item.path, saveDirectoryPath,
          onReceiveProgress: (count, total) {
        downloadProgressCallBack(
            count, total, item.id.toString(), saveDirectoryPath);
      });
    } catch (e) {
      print(e);
    }
  }

  void downloadProgressCallBack(
    count,
    total,
    String id,
    String filePath,
  ) {
    downloadFileList
        .firstWhere((element) => element.id == int.parse(id))
        .progress = count / total;
    update(["download"]);
    if (count == total) {
      downloadFileList
          .firstWhere((element) => element.id == int.parse(id))
          .isDownload = true;
      update(["download"]);
      if (filePath.endsWith('zip')) {
        unzipFiles(filePath, id);
      }
    }
  }

  Future<Directory> localfileDir() async {
    Directory? tempDir;
    if (GetPlatform.isAndroid) {
      tempDir = await getApplicationDocumentsDirectory();
    } else {
      tempDir = await getLibraryDirectory();
    }
    return tempDir;
  }

  Future unzipFiles(url, String id) async {
    // 获取到文件路径
    var dir = await localfileDir();
    String documentPath = dir.path;
    // 拿到文件的存储路径
    String savePath = "$documentPath/download/map";

    // 从磁盘读取zip文件
    List<int> bytes = File(url).readAsBytesSync();

    try {
      Archive archive = ZipDecoder().decodeBytes(bytes);
      List<String> pathFiles = [];
      // 将解码的文件解压缩到磁盘
      for (ArchiveFile file in archive) {
        if (file.isFile) {
          List<int> tempData = file.content;
          File f = File("$savePath/${file.name}")
            ..createSync(recursive: true)
            ..writeAsBytesSync(tempData);
          if (!f.path.contains('MACOSX')) {
            String clipFile = f.path.substring(dir.path.length);

            // myLog(f.path);
            pathFiles.add(clipFile);
          }
        } else {
          Directory("$savePath/${file.name}").create(recursive: true);
        }
      }
      saveDownloadListToCache();
      File(url).delete();
    } catch (e) {
      print(e);
    }
  }

// 保存下载列表到本地缓存
  Future<void> saveDownloadListToCache() async {
    final prefs = await SharedPreferences.getInstance();
    String listJson =
        jsonEncode(downloadFileList.map((e) => e.toJson()).toList());
    await prefs.setString('download_file_list', listJson);
  }

  // 从本地缓存读取下载列表
  Future<List<DownloadItemModel>> loadDownloadListFromCache() async {
    final prefs = await SharedPreferences.getInstance();
    String? listJson = prefs.getString('download_file_list');
    print(listJson);
    List<dynamic> tempList = jsonDecode(listJson!);
    return tempList.map((e) => DownloadItemModel.fromJson(e)).toList();
  }

  @override
  Future<void> onInit() async {
    await loadDownloadListFromCache().then((value) {
      downloadFileList = value;
    });
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
    _initData();
  }

  // @override
  // void onClose() {
  //   super.onClose();
  // }
}