使用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
相关产品推荐
相关产品推荐

