123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- import 'dart:io';
- import 'dart:typed_data';
- import 'package:fis_common/logger/logger.dart';
- import 'package:path_provider/path_provider.dart';
- import 'package:fis_common/env/env.dart';
- import 'package:idb_shim/idb.dart';
- import 'package:idb_shim/idb_browser.dart';
- /// 文件存储
- abstract class FileStorageNativeAndWeb {
- FileStorageNativeAndWeb({
- required this.directory,
- });
- /// 存储目录
- final String directory;
- Future<Uint8List?> read(String fileName) async {
- try {
- return await _getFile(fileName);
- } catch (e) {
- logger.e("File storage fetch fail, platform: ${FPlatform.current}.", e);
- return null;
- }
- }
- Future<bool> save(String fileName, Uint8List file) async {
- try {
- return await _setFile(fileName, file);
- } catch (e) {
- logger.e("Text storage save fail, platform: ${FPlatform.current}.", e);
- return false;
- }
- }
- Future<bool> delete(String fileName) async {
- try {
- return await _deleteFile(fileName);
- } catch (e) {
- logger.e("Text storage detail fail, platform: ${FPlatform.current}.", e);
- return false;
- }
- }
- Future<bool> deleteDirectory(String directoryPath) async {
- final storagePath = await _getStoragePath();
- final directory = Directory(storagePath);
- final result = await directory.exists();
- if (result) {
- try {
- await directory.delete(recursive: true);
- return true;
- } catch (e) {
- print(e);
- return false;
- }
- }
- return false;
- }
- Future<void> _checkAndCreateDir(String dir) async {
- final directory = Directory(dir);
- final parentDirectory = directory.parent;
- try {
- if (!await parentDirectory.exists()) {
- await parentDirectory.create(recursive: true);
- }
- } catch (e) {
- print(e);
- }
- if (!await directory.exists()) {
- try {
- await directory.create();
- } catch (e) {
- print(e);
- }
- }
- }
- Future<String> _getStoragePath() async {
- Directory? dir;
- if (Platform.isAndroid) {
- dir = await getExternalStorageDirectory();
- }
- dir ??= await getApplicationDocumentsDirectory();
- if (directory.isNotEmpty) {
- return "${dir.path}/$directory";
- }
- return dir.path;
- }
- Future<bool> _setFile(String fileName, Uint8List file);
- Future<Uint8List?> _getFile(String fileName);
- Future<bool> _deleteFile(String fileName);
- /// 创建实例
- ///
- /// [storageName] 文件名
- static FileStorageNativeAndWeb createInstance(String storageName) {
- final platform = FPlatform.current;
- switch (platform) {
- case FPlatformEnum.android:
- case FPlatformEnum.iOS:
- return _FileStorageNative(storageName);
- case FPlatformEnum.webOnMac:
- case FPlatformEnum.webOnWin:
- return _FileStorageShellWeb(storageName);
- case FPlatformEnum.web:
- return _FileStoragePureWeb(storageName);
- }
- }
- }
- ///本地化的文件存储
- class _FileStorageNative extends FileStorageNativeAndWeb {
- _FileStorageNative(String directory) : super(directory: directory);
- @override
- Future<Uint8List?> _getFile(String fileName) async {
- final storagePath = await _getStoragePath();
- final filePath = "$storagePath/$fileName";
- final file = File(filePath);
- if (!await file.exists()) return null;
- final text = await file.readAsBytes();
- return text;
- }
- @override
- Future<bool> _setFile(String fileName, Uint8List file) async {
- final storagePath = await _getStoragePath();
- final filePath = "$storagePath/$fileName";
- File fileToSave = File(filePath);
- _checkAndCreateDir(storagePath);
- if (!await fileToSave.exists()) {
- try {
- fileToSave = await fileToSave.create(recursive: true);
- } catch (e) {
- print(e);
- }
- }
- await fileToSave.writeAsBytes(file.toList());
- return true;
- }
- @override
- Future<String> _getStoragePath() async {
- Directory? dir;
- if (Platform.isAndroid) {
- dir = await getExternalStorageDirectory();
- }
- dir ??= await getApplicationDocumentsDirectory();
- return "${dir.path}/$directory";
- }
- @override
- Future<bool> _deleteFile(String fileName) async {
- final storagePath = await _getStoragePath();
- final filePath = "$storagePath/$fileName";
- final file = File(filePath);
- if (await file.exists()) {
- try {
- await file.delete();
- return true;
- } catch (e) {
- print(e);
- return false;
- }
- }
- return false;
- }
- }
- ///壳子下的文件存储
- class _FileStorageShellWeb extends FileStorageNativeAndWeb {
- _FileStorageShellWeb(String directory) : super(directory: directory);
- @override
- Future<Uint8List?> _getFile(String fileName) async {
- return null;
- }
- @override
- Future<bool> _setFile(String fileName, Uint8List file) async {
- return true;
- }
- @override
- Future<bool> _deleteFile(String fileName) async {
- return true;
- }
- }
- ///纯web端的文件缓存
- class _FileStoragePureWeb extends FileStorageNativeAndWeb {
- _FileStoragePureWeb(String directory) : super(directory: directory);
- static const int _version = 1;
- static const String _dbName = 'files.db';
- static const String _objectStoreName = 'files';
- static const String _propNameFilePath = 'filePath';
- static const String _propNameFileContents = 'contents';
- Future<Database> _openDb() async {
- final idbFactory = getIdbFactory();
- if (idbFactory == null) {
- throw Exception('getIdbFactory() failed');
- }
- return idbFactory.open(
- _dbName,
- version: _version,
- onUpgradeNeeded: (e) => e.database
- .createObjectStore(_objectStoreName, keyPath: _propNameFilePath),
- );
- }
- Future<bool> exists() async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadOnly);
- final store = txn.objectStore(_objectStoreName);
- final object = await store.getObject(directory);
- await txn.completed;
- return object != null;
- }
- Future<Uint8List> readAsBytes() async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadOnly);
- final store = txn.objectStore(_objectStoreName);
- final object = await store.getObject(directory) as Map?;
- await txn.completed;
- if (object == null) {
- throw Exception('file not found: $directory');
- }
- return object['contents'] as Uint8List;
- }
- Future<String> readAsString() async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadOnly);
- final store = txn.objectStore(_objectStoreName);
- final object = await store.getObject(directory) as Map?;
- await txn.completed;
- if (object == null) {
- writeAsBytes(Uint8List(0));
- return "";
- }
- return object['contents'] as String;
- }
- Future<void> writeAsBytes(Uint8List contents) async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadWrite);
- final store = txn.objectStore(_objectStoreName);
- await store.put({
- _propNameFilePath: directory,
- _propNameFileContents: contents
- }); // if the file exists, it will be replaced.
- await txn.completed;
- }
- Future<void> writeAsString(String contents) async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadWrite);
- final store = txn.objectStore(_objectStoreName);
- await store.put({
- _propNameFilePath: directory,
- _propNameFileContents: contents
- }); // if the file exists, it will be replaced.
- await txn.completed;
- }
- @override
- Future<Uint8List?> _getFile(String fileName) async {
- final uint8List = await readAsBytes();
- return uint8List;
- }
- @override
- Future<bool> _setFile(String fileName, Uint8List file) async {
- await writeAsBytes(file);
- return true;
- }
- @override
- Future<bool> _deleteFile(String fileName) async {
- final db = await _openDb();
- final txn = db.transaction(_objectStoreName, idbModeReadWrite);
- final store = txn.objectStore(_objectStoreName);
- await store.delete(directory);
- await txn.completed;
- return true;
- }
- }
|