file_cache_manager.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import 'dart:io';
  2. import 'dart:convert';
  3. import 'package:crypto/crypto.dart';
  4. import 'package:path_provider/path_provider.dart';
  5. import 'file_stream_util.dart';
  6. import 'log/logger.dart';
  7. class FileCacheManager {
  8. static const String TAG = 'FileCacheManager';
  9. static final FileCacheManager _instance = FileCacheManager._internal();
  10. factory FileCacheManager() => _instance;
  11. FileCacheManager._internal();
  12. late Directory _cacheDir;
  13. bool _isInitialized = false;
  14. /// 获取缓存目录
  15. Future<Directory> _getCacheDirectory() async {
  16. if (Platform.isIOS) {
  17. // iOS 使用应用文档目录
  18. final appDir = await getApplicationDocumentsDirectory();
  19. final cacheDir = Directory('${appDir.path}/skip_geo');
  20. if (!await cacheDir.exists()) {
  21. await cacheDir.create(recursive: true);
  22. }
  23. return cacheDir;
  24. } else {
  25. // Android 使用外部存储目录
  26. final appDir = await getExternalStorageDirectory();
  27. if (appDir == null) {
  28. throw Exception('Failed to get external storage directory');
  29. }
  30. final cacheDir = Directory('${appDir.path}/skip_geo');
  31. if (!await cacheDir.exists()) {
  32. await cacheDir.create(recursive: true);
  33. }
  34. return cacheDir;
  35. }
  36. }
  37. /// 初始化缓存管理器
  38. Future<void> init() async {
  39. if (_isInitialized) return;
  40. _cacheDir = await _getCacheDirectory();
  41. _isInitialized = true;
  42. }
  43. /// 获取文件内容,如果本地缓存有效则使用缓存,否则下载
  44. Future<String> getFileContent({
  45. required String remoteUrl,
  46. required String fileName,
  47. required String expectedMd5,
  48. required Function(double) onProgress,
  49. }) async {
  50. try {
  51. await init();
  52. final localFilePath = '${_cacheDir.path}/$fileName';
  53. log(TAG, 'localFilePath: $localFilePath');
  54. final localFile = File(localFilePath);
  55. // 检查本地文件是否存在且MD5匹配
  56. if (await localFile.exists()) {
  57. final localContent = await localFile.readAsString();
  58. final localMd5 = md5.convert(utf8.encode(localContent)).toString();
  59. if (localMd5 == expectedMd5) {
  60. return localContent;
  61. }
  62. }
  63. // 下载文件
  64. final result = await FileStreamUtils.readTextFile(
  65. path: remoteUrl,
  66. onProgress: onProgress,
  67. );
  68. // 验证下载文件的MD5
  69. // if (result.md5Hash == expectedMd5) {
  70. // // 保存到本地
  71. // }
  72. await localFile.writeAsString(result.content);
  73. return result.content;
  74. } catch (e) {
  75. log(TAG, 'FileCacheManager getFileContent error: $e');
  76. return '';
  77. }
  78. }
  79. /// 清除缓存
  80. Future<void> clearCache() async {
  81. try {
  82. await init();
  83. if (await _cacheDir.exists()) {
  84. await _cacheDir.delete(recursive: true);
  85. await _cacheDir.create();
  86. }
  87. } catch (e) {
  88. log(TAG, 'FileCacheManager clearCache error: $e');
  89. }
  90. }
  91. /// 获取缓存大小
  92. Future<int> getCacheSize() async {
  93. try {
  94. await init();
  95. if (!await _cacheDir.exists()) return 0;
  96. int totalSize = 0;
  97. await for (final file in _cacheDir.list(recursive: true)) {
  98. if (file is File) {
  99. totalSize += await file.length();
  100. }
  101. }
  102. return totalSize;
  103. } catch (e) {
  104. log(TAG, 'FileCacheManager getCacheSize error: $e');
  105. return 0;
  106. }
  107. }
  108. }