TauriJS writeBinaryFile报错Cannot freeze array buffer views
问题描述
使用TauriJS开发桌面应用时,借助jszip库修改zip压缩包内容,调用writeBinaryFile方法完成文件保存,原实现代码如下:
function saveFile(org_path, new_path, pack_format) { var zip = new JSZip(); // get file var org_file = await window.__TAURI__.fs.readBinaryFile(org_path); await zip.loadAsync(org_file); // edit file var pack_json = await zip.file("pack.json").async("string"); pack_json = JSON.parse(pack_json); pack_json.pack.pack_format = pack_format; zip.file("pack.json", JSON.stringify(pack_json)); // save file var array_zip = await zip.generateAsync({type:"uint8array"}); await window.__TAURI__.fs.writeBinaryFile(new_path, array_zip); }
运行代码时抛出未捕获类型错误:Uncaught TypeError: Cannot freeze array buffer views with elements,需要将jszip生成的zip文件转换为符合writeBinaryFile要求的格式,实现文件正常保存。
报错原因
Tauri v1版本的writeBinaryFile接口在接收参数时,会对传入的二进制对象执行冻结操作。jszip直接生成的Uint8Array是依附于原ArrayBuffer的视图对象,冻结这类携带元素的数组缓冲区视图时,就会触发该类型错误。
另外原代码存在语法疏漏:函数内部使用了await关键字,但函数声明未添加async标识,运行时也会触发语法错误。
修复方案
核心处理逻辑是在传入写入接口前,对jszip生成的二进制数据做一次拷贝,生成独立的、无外部依赖的二进制实例即可,两种可选实现方式:
- 方式1:保留Uint8Array输出类型,拿到jszip生成结果后,通过Uint8Array构造函数做一次浅拷贝,切断和原缓冲区的关联
- 方式2:调整jszip生成参数,指定输出类型为
arraybuffer,直接传入原始二进制缓冲区,也可规避该问题
修正后的可运行代码如下:
async function saveFile(org_path, new_path, pack_format) { const zip = new JSZip(); // 读取原压缩包文件 const org_file = await window.__TAURI__.fs.readBinaryFile(org_path); await zip.loadAsync(org_file); // 修改压缩包内的pack.json内容 const pack_json_raw = await zip.file("pack.json").async("string"); const pack_json = JSON.parse(pack_json_raw); pack_json.pack.pack_format = pack_format; zip.file("pack.json", JSON.stringify(pack_json)); // 生成压缩包并转换为符合接口要求的格式 const zip_data = await zip.generateAsync({type:"uint8array"}); // 关键步骤:拷贝生成独立的Uint8Array实例 const valid_data = new Uint8Array(zip_data); await window.__TAURI__.fs.writeBinaryFile(new_path, valid_data); }
内容的提问来源于stack exchange,提问作者Wolffe2
相关产品推荐
相关产品推荐

