如何在Dart中序列化/反序列化FileSystemHandle并存储到IndexedDB?
解决Dart js-interop存储FileSystemDirectoryHandle到IndexedDB的问题
问题根源在于Dart的JS代理对象会被自动转为Dart的LinkedMap结构存储,丢失了原生JS对象的身份,导致读取后无法还原为FileSystemDirectoryHandle实例。以下是可行的解决思路:
一、直接操作原生JS对象存储
核心是绕过Dart层的对象转换,直接将原生FileSystemDirectoryHandle对象存入IndexedDB:
提取原生JS对象
如果你通过package:js的@staticInterop注解定义了FileSystemDirectoryHandle类,使用dart:js_util的asJsObject方法从Dart代理中取出原生JS对象:import 'dart:js_util' as js_util; import 'package:js/js.dart'; @JS() @staticInterop class FileSystemDirectoryHandle {} // 假设directoryHandle是已获取的Dart代理对象 final nativeJsHandle = js_util.asJsObject(directoryHandle);调用原生IndexedDB API存储
避免使用Dart封装的IndexedDB库(这类库会自动将JS对象转为Dart结构),直接通过js-interop调用原生API存储:@JS() external IDBFactory get indexedDB; Future<void> storeDirectoryHandle(FileSystemDirectoryHandle handle) async { // 打开数据库 final dbRequest = indexedDB.open('fileHandlesDB', 1); dbRequest.onupgradeneeded = (_) { final db = dbRequest.result; db.createObjectStore('directoryHandles'); }; final db = await js_util.promiseToFuture(dbRequest); // 写入原生对象 final transaction = db.transaction('directoryHandles', 'readwrite'); final store = transaction.objectStore('directoryHandles'); await js_util.promiseToFuture(store.put(js_util.asJsObject(handle), 'defaultDir')); await js_util.promiseToFuture(transaction.complete); db.close(); }
二、读取后还原为Dart代理对象
从IndexedDB读取时,拿到的是原生JS对象,直接将其转为Dart的FileSystemDirectoryHandle代理即可:
Future<FileSystemDirectoryHandle> getStoredDirectoryHandle() async { final dbRequest = indexedDB.open('fileHandlesDB', 1); final db = await js_util.promiseToFuture(dbRequest); final transaction = db.transaction('directoryHandles', 'readonly'); final store = transaction.objectStore('directoryHandles'); final nativeHandle = await js_util.promiseToFuture(store.get('defaultDir')); db.close(); // 直接将原生JS对象转为Dart代理 return nativeHandle as FileSystemDirectoryHandle; }
关键注意事项
- 原生FileSystemHandle对象支持结构化克隆算法,可以直接存入IndexedDB,无需额外序列化。
- 必须使用原生IndexedDB API操作,避免Dart库的自动对象转换,否则会丢失原生对象的类型信息。
内容的提问来源于stack exchange,提问作者LPFreelance
相关产品推荐
相关产品推荐

