Files
cloud_archiver/client/lib/utils.dart
T
2026-07-13 08:16:54 +08:00

179 lines
5.1 KiB
Dart

import 'dart:io';
import 'package:archive/archive_io.dart';
import 'package:cloud_archiver/config.dart';
import 'package:cloud_archiver/state.dart';
import 'package:filesize/filesize.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webdav_client/webdav_client.dart' as dav;
late dav.Client _client;
String totalSize() {
if (cloudArchives.value.isEmpty) return '0 MB';
return filesize(
cloudArchives.value.values
.map((archives) => archives.map((archive) => archive.size ?? 0).reduce((total, size) => total + size))
.reduce((total, size) => total + size),
1,
);
}
Future<bool> connect(String server, String user, String auth) async {
var client = dav.newClient(
server,
debug: true,
user: user,
password: auth,
);
client.setHeaders({'accept-charset': 'utf-8'});
client.setConnectTimeout(5 * 1000);
// Set send data timeout time in milliseconds.
client.setSendTimeout(60 * 1000);
// Set transfer data time in milliseconds.
client.setReceiveTimeout(60 * 1000);
try {
davStatus.value = DavStatus.loading;
await client.ping();
davStatus.value = DavStatus.connected;
_client = client;
return true;
} catch (e) {
print('$e');
davStatus.value = DavStatus.notConnected;
}
return false;
}
void loadLocalStatus() {
if (appConfig?.syncItems.isNotEmpty != true) return;
var result = <SyncItemConfig, DateTime?>{};
for (var syncItem in appConfig!.syncItems) {
var file = File(syncItem.path);
var stat = file.statSync();
switch (stat.type) {
case FileSystemEntityType.file:
result[syncItem] = stat.modified;
case FileSystemEntityType.directory:
result[syncItem] = dirModifiedTime(syncItem.path);
default:
result[syncItem] = null;
}
}
localSyncItems.value = {
...localSyncItems.value,
...result,
};
}
DateTime dirModifiedTime(String dir) {
var directory = Directory(dir);
var modified = directory.statSync().modified;
for (var entry in Directory(dir).listSync(recursive: true)) {
var stat = entry.statSync();
if (stat.type == FileSystemEntityType.file) {
if (stat.modified.isAfter(modified)) {
modified = stat.modified;
}
}
}
return modified;
}
void loadCloudArchives() async {
if (davStatus.value != DavStatus.connected) return;
davStatus.value = DavStatus.loading;
List<dav.File> list = [];
try {
list = await _client.readDir('/');
} catch (e) {
print(e);
davStatus.value = DavStatus.notConnected;
return;
}
var result = <String, List<dav.File>>{};
for (var item in list) {
if (item.isDir == true && item.path?.isNotEmpty == true) {
var files = await _client.readDir(item.path!);
result[basename(item.path!)] = files;
}
}
cloudArchives.value = result;
davStatus.value = DavStatus.connected;
}
Future<void> upload(SyncItemConfig item, bool needCreateDir) async {
if (needCreateDir) {
await _client.mkdir(item.name);
}
var file = File(item.path);
var cacheDir = await getApplicationCacheDirectory();
var zipFileEncoder = ZipFileEncoder();
var zipFileName = '${appConfig?.client ?? 'DEBUG'}-${DateTime.now().strFileName}.zip';
var zipTempFilePath = join(cacheDir.path, zipFileName);
zipFileEncoder.create(zipTempFilePath);
if (file.statSync().type == FileSystemEntityType.directory) {
await zipFileEncoder.addDirectory(Directory(item.path));
} else {
await zipFileEncoder.addFile(file);
}
await zipFileEncoder.close();
await _client.writeFromFile(zipTempFilePath, join(item.name, zipFileName));
File(zipTempFilePath).delete();
loadCloudArchives();
}
Future<void> download(SyncItemConfig item, dav.File cloudArchive) async {
print('Start download: ${cloudArchive.path}');
var cacheDir = await getApplicationCacheDirectory();
var zipPath = join(cacheDir.path, '${item.name}_${cloudArchive.name}');
await _client.read2File(cloudArchive.path!, zipPath);
await extractFileToDisk(zipPath, cacheDir.path);
File(zipPath).delete();
var temp = File(join(cacheDir.path, basename(item.path)));
print('Temp path: ${temp.path}');
var fileSystemEntityType = temp.statSync().type;
switch (fileSystemEntityType) {
case FileSystemEntityType.directory:
var directory = Directory(item.path);
if (directory.existsSync()) {
directory.deleteSync(recursive: true);
}
Directory(temp.path);
Directory(temp.path).renameSync(item.path);
case FileSystemEntityType.file:
var file = File(item.path);
if (file.existsSync()) {
file.deleteSync();
}
temp.renameSync(item.path);
default:
print('Failed: $fileSystemEntityType');
}
}
extension DateTimeExt on DateTime {
String get strHm => '$year/${padZero(month)}/${padZero(day)} ${padZero(hour)}:${padZero(minute)}';
String get strHms => '$strHm:${padZero(second)}';
String get strFileName => '${year}_${padZero(month)}_${padZero(day)}_${padZero(hour)}_${padZero(minute)}_${padZero(second)}';
String padZero(int num, [fix = 2]) => num.toString().padLeft(fix, '0');
}