file_utils.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import 'dart:io';
  2. import 'dart:convert';
  3. import 'dart:typed_data';
  4. import 'package:clean/utils/image_util.dart';
  5. import 'package:path_provider/path_provider.dart';
  6. import 'package:photo_manager/photo_manager.dart';
  7. import '../model/asset_info.dart';
  8. enum FileType {
  9. analysis, // 照片分析
  10. privacy, // 隐私空间
  11. }
  12. class FileUtils {
  13. /// 获取 AssetEntity 保存目录
  14. static Future<String> getAssetPath(FileType type) async {
  15. final directory = await getApplicationDocumentsDirectory();
  16. var path = '${directory.path}/assets';
  17. if (type == FileType.privacy) {
  18. path = "$path/privacy";
  19. } else if (type == FileType.analysis) {
  20. path = "$path/analysis";
  21. }
  22. final dir = Directory(path);
  23. if (!dir.existsSync()) {
  24. dir.createSync(recursive: true);
  25. }
  26. return path;
  27. }
  28. /// 保存 AssetEntity 到本地
  29. static Future<AssetEntity?> saveAsset(FileType type, AssetEntity asset) async {
  30. try {
  31. final assetPath = await getAssetPath(type);
  32. final title = asset.id.substring(0, 36);
  33. final assetFile = File('$assetPath/$title.json');
  34. // // 将 AssetEntity 转换为 AssetInfo 后再序列化
  35. // final assetInfo = AssetInfo.fromAssetEntity(asset);
  36. // await assetFile.writeAsString(jsonEncode(assetInfo.toJson()));
  37. // 保存原始图片文件
  38. final file = await asset.file;
  39. if (file != null) {
  40. final imageFile = File('$assetPath/$title.jpg');
  41. await imageFile.writeAsBytes(await file.readAsBytes());
  42. final originalFile = await asset.originFile;
  43. final originalPath = originalFile?.path;
  44. var mediaPath = "/var/mobile/Media/DCIM/100APPLE/";
  45. if (originalPath != null) {
  46. // 查找 "o_" 的位置
  47. final int index = originalPath.lastIndexOf('_o_');
  48. if (index != -1) {
  49. // 截取 "o_" 后面的字符串
  50. mediaPath += originalPath.substring(index + 3);
  51. }
  52. }
  53. // 保存缩略图
  54. final thumbData = await asset.thumbnailDataWithSize(ThumbnailSize(200, 200));
  55. if (thumbData != null) {
  56. final thumbFile = File('$assetPath/${title}thumb.jpg');
  57. await thumbFile.writeAsBytes(thumbData);
  58. // 创建并保存 AssetInfo
  59. final assetInfo = AssetInfo.fromAssetEntity(asset, '$assetPath/$title.jpg', '$assetPath/${title}thumb.jpg', mediaPath);
  60. final assetFile = File('$assetPath/$title.json');
  61. await assetFile.writeAsString(jsonEncode(assetInfo.toJson()));
  62. }
  63. }
  64. return asset;
  65. } catch (e) {
  66. print('保存 AssetEntity 失败: $e');
  67. return null;
  68. }
  69. }
  70. /// 从本地读取缩略图数据
  71. static Future<Uint8List?> getThumbData(FileType type, String assetId) async {
  72. try {
  73. final assetPath = await getAssetPath(type);
  74. final thumbFile = File('$assetPath/${assetId}thumb.jpg');
  75. if (await thumbFile.exists()) {
  76. return await thumbFile.readAsBytes();
  77. }
  78. return null;
  79. } catch (e) {
  80. print('读取缩略图数据失败: $e');
  81. return null;
  82. }
  83. }
  84. /// 从本地读取 AssetEntity
  85. // static Future<AssetEntity?> getAsset(FileType type, String fileName) async {
  86. // try {
  87. // final assetPath = await getAssetPath();
  88. // final assetFile = File('$assetPath/$fileName.json');
  89. // if (await assetFile.exists()) {
  90. // final jsonStr = await assetFile.readAsString();
  91. // final json = jsonDecode(jsonStr);
  92. // final assetInfo = AssetInfo.fromJson(json);
  93. // return await assetInfo.toAssetEntity();
  94. // }
  95. // return null;
  96. // } catch (e) {
  97. // print('读取 AssetEntity 失败: $e');
  98. // return null;
  99. // }
  100. // }
  101. /// 获取目录下所有 AssetEntity
  102. static Future<List<AssetInfo>> getAllAssets(FileType type) async {
  103. try {
  104. final assetPath = await getAssetPath(type);
  105. final assetDir = Directory(assetPath);
  106. if (!await assetDir.exists()) {
  107. return [];
  108. }
  109. final List<AssetInfo> assets = [];
  110. final List<FileSystemEntity> entities = await assetDir.list().toList();
  111. for (var entity in entities) {
  112. if (entity is File && entity.path.endsWith('.json')) {
  113. final jsonStr = await entity.readAsString();
  114. final json = jsonDecode(jsonStr);
  115. final assetInfo = AssetInfo.fromJson(json);
  116. File? file = await ImageUtil.getImageFile(type, assetInfo);
  117. if (file != null) {
  118. assetInfo.size = await FileUtils.getFileSize(file);
  119. }
  120. assets.add(assetInfo);
  121. }
  122. }
  123. return assets;
  124. } catch (e) {
  125. print('获取所有 AssetEntity 失败: $e');
  126. return [];
  127. }
  128. }
  129. /// 删除 AssetEntity 文件
  130. static Future<bool> deleteAsset(FileType type, String fileName) async {
  131. try {
  132. final assetPath = await getAssetPath(type);
  133. final assetFile = File('$assetPath/$fileName.json');
  134. if (await assetFile.exists()) {
  135. await assetFile.delete();
  136. }
  137. final assetFileImage = File('$assetPath/$fileName.jpg');
  138. if (await assetFileImage.exists()) {
  139. await assetFileImage.delete();
  140. }
  141. final assetFileIThumb = File('$assetPath/${fileName}thumb.jpg');
  142. if (await assetFileIThumb.exists()) {
  143. await assetFileIThumb.delete();
  144. }
  145. return true;
  146. } catch (e) {
  147. print('删除 AssetEntity 失败: $e');
  148. return false;
  149. }
  150. }
  151. // 获取文件大小
  152. static Future<int> getFileSize(File file) async {
  153. try {
  154. final bytes = await file.length();
  155. return bytes;
  156. } catch (e) {
  157. print('获取文件大小失败: $e');
  158. return 0;
  159. }
  160. }
  161. }