import 'dart:ffi'; import 'dart:io'; import 'package:classify_photo/classify_photo.dart'; import 'package:flutter/cupertino.dart'; import 'package:wechat_assets_picker/wechat_assets_picker.dart'; import 'package:photo_manager/photo_manager.dart'; class FileSizeCalculatorUtil { static final Map fileSizeCache = {}; static Future calculateTotalSizeByIOS({ required Set assetIds, required Function(double) updateValue, }) async { if (assetIds.isEmpty) { updateValue(0); return; } double totalSize = 0; totalSize = await ClassifyPhoto().calculatePhotosSize(assetIds.toList()) / 1024; updateValue(totalSize); } static Future calculateTotalSizeByAndroid({ required Set assetIds, required Function(double) updateValue, }) async { if (assetIds.isEmpty) { updateValue(0); return; } double totalSize = 0; final uncasedIds = assetIds.where((id) => !fileSizeCache.containsKey(id)).toSet(); // **1️⃣ 先处理缓存中的文件** totalSize = assetIds.fold(0, (prev, id) => prev + (fileSizeCache[id] ?? 0)); updateValue(totalSize); // **2️⃣ 分批处理未缓存的文件** const batchSize = 20; for (int i = 0; i < uncasedIds.length; i += batchSize) { if (assetIds.isEmpty) { updateValue(0); return; } final batch = uncasedIds.skip(i).take(batchSize); final sizes = await Future.wait(batch.map(FileSizeCalculatorUtil.getFileSize)); totalSize += sizes.fold(0, (sum, size) => sum + size); // **再检查一次是否被清空,避免无意义计算** if (assetIds.isEmpty) { updateValue(0); return; } await Future.delayed(Duration.zero); updateValue(totalSize); } updateValue(totalSize); } static Future calculateTotalSize({ required Set assetIds, required Function(double) updateValue, }) async { if (Platform.isIOS) { await calculateTotalSizeByIOS( assetIds: assetIds, updateValue: updateValue); } else { await calculateTotalSizeByAndroid( assetIds: assetIds, updateValue: updateValue); } } /// 获取文件大小 static Future getFileSize(String assetId) async { if (fileSizeCache.containsKey(assetId)) { return fileSizeCache[assetId]!; } final entity = await AssetEntity.fromId(assetId); if (entity == null) return 0; if (Platform.isAndroid) { final String? path = entity.relativePath; if (path == null) return 0; final file = File("/storage/emulated/0/$path${entity.title}"); // print("file path: ${await file.path}"); if (!await file.exists()) { return 0; } // print("file size: ${await file.length()}"); final double size = (await file.length()) / 1024; fileSizeCache[assetId] = size; return size; } else { final file = await entity.file; if (file == null) return 0; if (!await file.exists()) { return 0; } try { final double size = (await file.length()) / 1024; fileSizeCache[assetId] = size; try { await file.delete(); } catch (e) { debugPrint("Delete file error: $e"); } if (size <= 0) { return 0; } return size; } catch (e) { return 0; } } } }