使用Vanilla JavaScript无需弹窗指定路径直接读写JSON文件
用原生JavaScript实现指定路径JSON文件的创建/更新
问题背景
已有通过系统弹窗选择文件进行读写的可行代码,但需要实现已知路径和文件名的JSON文件创建/更新,尝试手动构造FileSystemFileHandle对象失败。
现有弹窗选择文件的代码
async function Save_JSON_File() { // 创建新的文件句柄 newHandle = await window.showSaveFilePicker(); var l = "mmm mmm " // 创建可写文件流 const writableStream = await newHandle.createWritable(); // 写入内容 await writableStream.write(l); // 关闭流并写入磁盘 await writableStream.close(); }
核心问题
FileSystemFileHandle对象是浏览器通过文件选择器API返回的,内置了安全上下文绑定的访问权限,手动构造的对象不具备有效权限,无法执行文件读写操作。
适合本地运行场景的解决方案
你的应用是存储在外部存储设备的本地静态应用,完全支持File System Access API,可通过以下两种方式实现指定路径的文件操作:
方案1:通过目录权限持久化实现指定路径文件操作
先让用户选择一次目标目录,获取目录句柄并持久化权限,之后就能在该目录下直接创建/更新指定文件:
// 全局变量存储持久化的目录句柄 let targetDirHandle; // 首次选择目标目录并申请持久化权限 async function selectTargetDirectory() { targetDirHandle = await window.showDirectoryPicker({ mode: 'readwrite' }); // 确保获取读写权限 if (await targetDirHandle.queryPermission({ mode: 'readwrite' }) !== 'granted') { await targetDirHandle.requestPermission({ mode: 'readwrite' }); } } // 创建/更新指定文件名的JSON文件 async function writeJSONFile(fileName, jsonContent) { if (!targetDirHandle) { alert('请先选择目标目录'); await selectTargetDirectory(); } // 获取文件句柄,不存在则自动创建 const fileHandle = await targetDirHandle.getFileHandle(fileName, { create: true }); // 创建可写流并写入格式化后的JSON const writableStream = await fileHandle.createWritable(); await writableStream.write(JSON.stringify(jsonContent, null, 2)); await writableStream.close(); console.log(`文件${fileName}已成功创建/更新`); }
使用方式:先调用selectTargetDirectory()让用户选择一次U盘里的目标文件夹,之后直接调用writeJSONFile('demo.json', {title: '演示数据', content: []})即可创建/更新指定文件。
方案2:存储文件句柄实现固定文件操作
如果只需要操作某个特定文件,可在用户首次选择后,将文件句柄的标识存储到本地存储,下次打开应用时直接恢复:
// 保存文件句柄到本地存储 async function saveFileHandle() { const fileHandle = await window.showSaveFilePicker(); const handleId = await fileHandle.toString(); localStorage.setItem('targetFileHandle', handleId); } // 从本地存储恢复文件句柄 async function getTargetFileHandle() { const handleId = localStorage.getItem('targetFileHandle'); if (handleId) { try { return await window.getFileHandleFromID(handleId); } catch (error) { // 权限过期或文件不存在,重新选择 localStorage.removeItem('targetFileHandle'); return await window.showSaveFilePicker(); } } else { return await window.showSaveFilePicker(); } } // 更新指定JSON文件 async function updateJSONContent(jsonContent) { const fileHandle = await getTargetFileHandle(); const writableStream = await fileHandle.createWritable(); await writableStream.write(JSON.stringify(jsonContent, null, 2)); await writableStream.close(); }
注意:若用户清除浏览器数据或权限过期,需要重新选择文件。
关键提示
- 不能手动构造
FileSystemFileHandle对象,必须通过浏览器提供的文件/目录选择器API获取,这类对象携带了浏览器授予的文件系统访问权限,手动构造的对象无权限执行读写。 - 本地静态应用完全支持File System Access API,无需部署到公网。
内容的提问来源于stack exchange,提问作者FDavidov
相关产品推荐
相关产品推荐

