You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dart中序列化/反序列化FileSystemHandle并存储到IndexedDB?

解决Dart js-interop存储FileSystemDirectoryHandle到IndexedDB的问题

问题根源在于Dart的JS代理对象会被自动转为Dart的LinkedMap结构存储,丢失了原生JS对象的身份,导致读取后无法还原为FileSystemDirectoryHandle实例。以下是可行的解决思路:

一、直接操作原生JS对象存储

核心是绕过Dart层的对象转换,直接将原生FileSystemDirectoryHandle对象存入IndexedDB:

  1. 提取原生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);
    
  2. 调用原生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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:05:14