197 lines
4.8 KiB
Dart
197 lines
4.8 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import '../interfaces/resume_storage.dart';
|
|
|
|
// 注意:这个实现需要 path_provider 包
|
|
// 在实际使用时需要在 pubspec.yaml 中添加 path_provider: ^2.1.0
|
|
|
|
/// 基于本地文件的断点续传存储实现
|
|
class LocalResumeStorage implements ResumeStorage {
|
|
static const String _storageDir = 'yx_oss_resume';
|
|
static const String _fileExtension = '.json';
|
|
|
|
Directory? _cacheDirectory;
|
|
|
|
/// 获取缓存目录
|
|
Future<Directory> get cacheDirectory async {
|
|
if (_cacheDirectory != null) {
|
|
return _cacheDirectory!;
|
|
}
|
|
|
|
// 简化实现:使用临时目录,避免依赖 path_provider
|
|
// 在实际集成时可以替换为 getApplicationDocumentsDirectory()
|
|
final tempDir = Directory.systemTemp;
|
|
_cacheDirectory = Directory('${tempDir.path}/$_storageDir');
|
|
|
|
// 确保目录存在
|
|
if (!await _cacheDirectory!.exists()) {
|
|
await _cacheDirectory!.create(recursive: true);
|
|
}
|
|
|
|
return _cacheDirectory!;
|
|
}
|
|
|
|
/// 获取任务文件路径
|
|
Future<File> _getTaskFile(String taskId) async {
|
|
final dir = await cacheDirectory;
|
|
return File('${dir.path}/$taskId$_fileExtension');
|
|
}
|
|
|
|
@override
|
|
Future<void> saveResumeInfo(
|
|
String taskId, Map<String, dynamic> resumeInfo) async {
|
|
try {
|
|
final file = await _getTaskFile(taskId);
|
|
final jsonString = jsonEncode(resumeInfo);
|
|
await file.writeAsString(jsonString);
|
|
} catch (e) {
|
|
throw Exception('Failed to save resume info for task $taskId: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<Map<String, dynamic>?> loadResumeInfo(String taskId) async {
|
|
try {
|
|
final file = await _getTaskFile(taskId);
|
|
|
|
if (!await file.exists()) {
|
|
return null;
|
|
}
|
|
|
|
final jsonString = await file.readAsString();
|
|
return jsonDecode(jsonString) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
// 文件损坏或格式错误时删除文件
|
|
try {
|
|
final file = await _getTaskFile(taskId);
|
|
if (await file.exists()) {
|
|
await file.delete();
|
|
}
|
|
} catch (_) {
|
|
// 忽略删除错误
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> deleteResumeInfo(String taskId) async {
|
|
try {
|
|
final file = await _getTaskFile(taskId);
|
|
if (await file.exists()) {
|
|
await file.delete();
|
|
}
|
|
} catch (e) {
|
|
// 忽略删除错误,可能文件已不存在
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<List<String>> getAllTaskIds() async {
|
|
try {
|
|
final dir = await cacheDirectory;
|
|
if (!await dir.exists()) {
|
|
return [];
|
|
}
|
|
|
|
final files = await dir.list().toList();
|
|
final taskIds = <String>[];
|
|
|
|
for (final file in files) {
|
|
if (file is File && file.path.endsWith(_fileExtension)) {
|
|
final fileName = file.path.split('/').last;
|
|
final taskId =
|
|
fileName.substring(0, fileName.length - _fileExtension.length);
|
|
taskIds.add(taskId);
|
|
}
|
|
}
|
|
|
|
return taskIds;
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> clearAll() async {
|
|
try {
|
|
final dir = await cacheDirectory;
|
|
if (await dir.exists()) {
|
|
await dir.delete(recursive: true);
|
|
}
|
|
_cacheDirectory = null; // 重置缓存目录
|
|
} catch (e) {
|
|
// 忽略删除错误
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<int> getStorageSize() async {
|
|
try {
|
|
final dir = await cacheDirectory;
|
|
if (!await dir.exists()) {
|
|
return 0;
|
|
}
|
|
|
|
int totalSize = 0;
|
|
final files = await dir.list().toList();
|
|
|
|
for (final file in files) {
|
|
if (file is File) {
|
|
final stat = await file.stat();
|
|
totalSize += stat.size;
|
|
}
|
|
}
|
|
|
|
return totalSize;
|
|
} catch (e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/// 清理过期的断点续传信息
|
|
///
|
|
/// [maxAge] 最大保留时间(天数)
|
|
Future<void> cleanupExpiredTasks(int maxAge) async {
|
|
try {
|
|
final dir = await cacheDirectory;
|
|
if (!await dir.exists()) {
|
|
return;
|
|
}
|
|
|
|
final cutoffTime = DateTime.now().subtract(Duration(days: maxAge));
|
|
final files = await dir.list().toList();
|
|
|
|
for (final file in files) {
|
|
if (file is File && file.path.endsWith(_fileExtension)) {
|
|
final stat = await file.stat();
|
|
if (stat.modified.isBefore(cutoffTime)) {
|
|
try {
|
|
await file.delete();
|
|
} catch (_) {
|
|
// 忽略删除错误
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// 忽略清理错误
|
|
}
|
|
}
|
|
|
|
/// 获取任务的文件大小
|
|
Future<int> getTaskFileSize(String taskId) async {
|
|
try {
|
|
final file = await _getTaskFile(taskId);
|
|
if (await file.exists()) {
|
|
final stat = await file.stat();
|
|
return stat.size;
|
|
}
|
|
return 0;
|
|
} catch (e) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|