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

使用Safari中WebKit的FileSystem API刷新文件时数据丢失问题

FileSystem API写入数据后flush()文件变空的问题解决

你的核心问题是:使用FileSystemSyncAccessHandle写入数据后,没有更新文件的实际大小,导致flush时系统只保留原大小(0字节)的内容,写入的数据全部被丢弃。

错误原因分析

  • 新创建的文件初始大小为0,你写入了27字节的数据,但文件的逻辑大小仍然是0
  • flush()方法只会将当前文件大小范围内的数据持久化到磁盘,超出部分不会被保留
  • 即使写入成功,没有调整文件大小的话,后续读取或重启浏览器后,文件都会显示为0字节

修正后的代码

console.log("Starting");
async function files() {
    // Set a Message
    const message = "Thank you for reading this.";
    const fileName = "Draft.txt";

    // Get handle to draft file
    const root = await navigator.storage.getDirectory();
    const draftHandle = await root.getFileHandle(fileName, { create: true });
    console.log("File Name: ", fileName);
    
    // Get sync access handle
    const accessHandle = await draftHandle.createSyncAccessHandle();

    // Get size of the file.
    const fileSize = await accessHandle.getSize();
    console.log("File Size: ", fileSize); 

    // Write the message to the file.
    const encoder = new TextEncoder();
    const encodedMessage = encoder.encode(message);
    // 从文件起始位置写入数据
    const writeBuffer = accessHandle.write(encodedMessage, { at: 0 });
    console.log("Write: ", writeBuffer); 

    // 关键:更新文件大小为写入后的总长度
    await accessHandle.truncate(encodedMessage.length);
    
    // Persist changes to disk.
    accessHandle.flush();

    // Always close FileSystemSyncAccessHandle if done.
    accessHandle.close();
    console.log("Closed file ");

    // Find files under root/ and print their details.
    for await (const handle of root.values()) {
        console.log('Item in root: ', handle.name);
        if (handle.kind == "file") {
            let f = await handle.getFile();
            console.log("File Details: ", f); 
            // 现在可以看到文件大小正确,且包含数据
            const content = await f.text();
            console.log("File Content: ", content);
        }
    }
}

files();

关键修改点

  • 移除了不必要的初始读取逻辑(新文件本来就是空的,读取没有意义)
  • 写入时直接从at: 0位置开始写,逻辑更清晰
  • 新增await accessHandle.truncate(encodedMessage.length):将文件大小设置为写入数据的长度,确保flush时所有写入的数据都被持久化

验证说明

修改后执行代码,你会看到文件大小显示为27字节,读取内容能得到写入的字符串;重启Safari后再次执行读取逻辑,文件数据依然存在,不会变成0字节。

内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:56:01