预检清单
- 我已阅读此项目的 Contributing Guidelines。
- 我同意遵循此项目遵循的 Code of Conduct 。
- 我在 issue tracker 中搜索了一个与我想提交的功能请求相匹配的功能请求,但没有成功。
问题描述
当前解决方案
一个未沙盒化的electron预加载器具有 Blob 类以及 'fs' 模块。
以下代码确实提供了从文件路径到 Blob 和反向转换的方法:
const fs = require('fs');
// convert system file into blob
function fileToBlob(path, {bufferSize=64*1024}={}) {
return new Promise((resolve,reject) => {
// create incoming stream from file
const stream = fs.createReadStream(path, {highWaterMark:bufferSize});
// initialize empty blob
var blob = new Blob([]);
stream.on('data', buffer => {
// append each chunk to blob by building new blob concatenating new chunk
blob = new Blob([blob, buffer]);
});
stream.on('close', () => {
// resolve with resulting blob
resolve(blob);
});
});
}
// convert blob into system file
function blobToFile(blob,path, {bufferSize=64*1024}={}) {
return new Promise((resolve,reject) => {
// create outgoing stream to file
const stream = fs.createWriteStream(path);
stream.on('ready', async () => {
// iterate chunks at a time
for(let i=0; i<blob.size; i+=bufferSize) {
// read chunk
let slice = await blob.slice(i, i+bufferSize).arrayBuffer();
// write chunk
if(!stream.write(new Uint8Array(slice))) {
// wait for next drain event
await new Promise(resolve => stream.once('drain', resolve));
}
}
// close file and resolve
stream.on('close', () => resolve());
stream.close();
});
});
}
module.exports = {
fileToBlob,
blobToFile,
};
当前解决方案的问题
对于小文件,这没有任何缺点,运行良好。但是当处理多兆字节文件时,这是非常不切实际和缓慢的,因为它需要逐字节读取和复制整个文件。
Chromium现有机制
现在,Chromium已经支持立即生成文件到blob(一种将blob直接附加到文件的类型;如果文件被修改,blob也会改变)。这在拖放API以及 <input type="file">
输入中很明显。
相反,Chromium也支持相当快速的blob到文件生成。这可以在创建blob URL并下载它时看到(它实际上是以操作系统级别的文件复制速度下载;所以,足够了,但不是技术上的即时)。
建议的添加
由于blob对于许多渲染上下文操作(如播放视频: https://stackoverflow.com/questions/59133969/play-a-blob-video-file )是必需的,并且通常用于大文件,因此变得非常必要能够立即使用Chromium在其拖放API中的相同机制从文件生成blob。
反过来,对于修改blob(例如通过切片、生成和重新连接到新blob)的应用程序来说,能够以原生速度导出blob也是非常有帮助的,同样使用Chromium或类似机制。具体来说,虽然可以通过通过blob URL下载blob来实现这一点,但这种机制将避免下载文件对话框。
建议的解决方案
有许多方法可以实现这一点。一种简单的、直接的方法可以在启用了 nodeIntegration
的预加载器或渲染器上对electron模块进行一些 blobToFile
/ fileToBlob
方法:
const { fileBlob } = require('electron');
// generate blob from file
var blob = fileBlob.fileToBlob("C:/Users/Example/Desktop/foo.txt");
var newBlob = new Blob( [blob.slice(100,200), blob.slice(0,100)] );
// save blob to file
fileBlob.blobToFile("C:/Users/Example/Desktop/foo-reversed.txt");
请注意,上述函数是同步编写的,但异步方法也可以。
然而,我知道,由于Blob在node.js中不受支持,如果没有某种Blob polyfill,像'fileBlob'这样的模块将无法在node.js electron模块中使用。我的主要请求是在至少渲染器预加载器环境中提供一种方法。
考虑过的其他方案
我找到了以下类似的请求存在,问题 #749 ,它建议使文件输入的值可修改。解决该问题也将解决此问题。解决此问题不会为该问题提供精确的解决方案,但在大多数(或可能所有)情况下都会足够。
6条答案
按热度按时间bnlyeluc1#
我强烈觉得我们需要这个功能。
我的用例:在一个医疗应用中,文件存储在本地文件系统(其路径存储在IndexDB数据库中),需要通过一个以blob格式访问的模块来访问这些文件。这个模块来自第三方,所以不能更改它。
2mbi3lxu2#
我需要这个功能:filePathToBlob()
vmdwslir3#
嘿,Andrew,感谢你认真的撰写和提议!
我不知道是否已经计划了这项工作,但为了澄清——我认为你是建议自己编写这个提案,但从你的撰写中我不确定,所以我想问一下而不是做出假设?
如果你自愿参与这个提案的工作,那么我认为下一步应该是将这个提案转发给API工作组进行审查。
tpgth1q74#
感谢@ckerr。
我的目的只是提出这个功能。即使如此,如果我熟悉Electron/Chromium代码库,我也愿意自己编写它。我可以尝试添加这个功能吗?还是最好让熟悉该代码区域的人来帮助避免bug/安全漏洞?
如果你不认为这很重要,也许可以帮我指明正确的方向(我以前没有为electron贡献过)。我不反对尝试,我完全愿意帮助使一个已经很棒的项目变得更好😄。
eit6fx6z5#
你好,@CodeSmith32,
听起来很棒,谢谢!在我们讨论实现之前,我认为第一步应该是API工作组审查你的提案,因为那里提出的任何更改都将影响实现。我之前的评论主要是想了解你是否自愿承担这项工作,因为我不希望在没有冠军的情况下向API工作组提出提案😸
CC @electron/wg-api
gudnpqoy6#
File System Access API 可以帮助解决这个问题。在最新的夜间测试中,以下代码可以读取文件到 blob:
使用
window.showOpenFilePicker()
的一个注意事项是,它需要用户选择一个文件。此外,似乎将 blob 写入文件会在 Electron 中抛出错误(可能是因为 Chromium 对安全上下文的 File System Access API 限制):