在阅读文件api并希望直接将数据从indexeddb数据库写入客户机磁盘而不是首先在ram中构建并保存一个大blob以下载到磁盘时,有一些基本的问题我不理解。
在MDN文档中可以找到这两个语句:
在gecko中,特权代码可以创建表示任何本地文件的文件对象,而无需用户交互。
如果您想在chrome代码中使用dom文件api,您可以不受限制地这样做。实际上,还有一个额外的功能:可以创建文件对象,指定用户计算机上文件的路径。这只适用于特权代码,所以web内容不能这样做。
-
在哪里写chrome代码和/或gecko私有代码?这超出了Web扩展的范围吗?我已经阅读并尝试过扩展;所以,我并没有特别询问如何访问它们。
我不担心“正常”的网页和服务器访问客户机磁盘。我知道为了保护个人是不允许的。
我很感兴趣的是,如果有个人有意使用浏览器来完成他们应该在操作系统而不是浏览器中构建的工作,那么可以通过浏览器脱机完成的工作——借助于Web扩展和/或单独的配置文件授予特殊权限,但不需要node.js、electron等。
-
换言之,如果我想使用浏览器运行javascript代码,在自己的机器上执行所有脱机任务,那么编写的特权代码在哪里,可以访问这些不受普通网页安全问题影响的api类型?
-
在这些领域,它仍然是javascript还是c++呢?
谢谢您。
This old question
提供指向其
extension
其中包括文件api,该api以一种似乎提供了绕过创建大数据块的方法的方式写入磁盘。它已经有六年的历史了,但似乎包含了所需要的东西,至少是开始的时候。
我指的不是他们试图绕过使用indexeddb,而是使用这种类型的扩展可以允许将每个对象从数据库直接写入客户机磁盘,而不必首先生成一个要下载的大blob。
试图采纳安德鲁·斯旺的建议
我正试着把这些碎片拼凑起来,但已经到了不确定如何继续下去的地步。我在扩展的后台脚本中编写了下面的代码。在尝试采用andrew swan的建议时,计划是初始化一个文本/csv文件的get请求,该请求被截取并替换为从数据库提取的数据,并由流过滤器写入get请求。
首先,对一个假的url发出get请求并监听响应,如下所示:
let request = new XMLHttpRequest();
request.open("GET", url );
request.setRequestHeader( "Content-Type", "text/csv" );
request.send(null);
request.onreadystatechange = () =>
{
portFromCS.postMessage( { 'func' : 'disp_result', 'args' : { 'msg' : "request.status :", 'value' : request.status + ' : ' + request.statusText} } );
};
其次,截取请求并写入get,如下所示:
browser.webRequest.onBeforeRequest.addListener(
listener,
{ urls : ["<all_urls>"] },
["blocking"] );
function listener( details )
{
let filter = browser.webRequest.filterResponseData(details.requestId);
let decoder = new TextDecoder("utf-8");
let encoder = new TextEncoder();
filter.onstart = event =>
{
let str = decoder.decode(event.data, {stream: true});
str = '' +
'HTTP/1.1 200 OK \r\n' +
'Content-Length: 17 \r\n' +
'Content-Type: text/csv \r\n\r\n\r\n' +
'This is a string.';
filter.write(encoder.encode(str));
filter.disconnect();
};
}
从request.onreadystatechange函数中的后台脚本发送的消息在内容脚本中接收,request.status为“0”。
之所以使用filter.onstart,是因为ondata事件永远不会触发,因为url是假的。另外,这意味着不会转换来自url的数据,只会通过过滤器写入新数据。
str数据由请求写入和接收,但仅作为responsetext而不是作为响应头。request.status保持为“0”,而不是“200”。
似乎无法更改响应头,除非在onheadersreceived中,它似乎永远不会发生,因为一个虚假的url。但是,我在一个真实的url上尝试了这个方法,即使触发了事件,webrequest.httpheaders的错误也不是函数。当时我在webrequest extrainfospec中有“responseheaders”。
我的问题是:
-
是否可以写入响应头以将request.status设置为“200”,然后在检索到时通过异步函数以小块形式开始写入数据库数据?
-
是否可以设置头响应的内容配置部分,使其自动启动response.text的下载,并允许用户选择文件名和保存位置,并在从数据库提取数据并通过filter.write()传递给get请求时保持“打开”状态以继续写入文件?
谢谢您。
结论
这是个好主意,但我认为至少有两个原因是不可能的。
一个是webrequest似乎根本没有截获downloads.download()函数或任何下载事件;因此,您无法截获下载,甚至需要一个内容配置为“attachment”的事件来尝试用流向其写入。我可以拦截对锚标记的强制单击,但除了onbeforerequest之外,没有其他事件被触发。
另一种是在onheadersreceived事件之前不能修改响应头,这意味着假url必须返回一些内容。你不能按事先的要求取消它。所以,这在离线状态下是行不通的。但是,即使让它在线处理返回响应头的现有url,它也不会接受修改。我反复尝试修改响应头,但它不起作用。我尝试了一个xmlhttprequest get,它可以拦截触发的事件,但无法修改响应头;因此,无法将内容配置设置为“附件”,无论是否有文件,都无法启动下载。我可以给它写信,但如果它不下载我写的东西,那就没用了。如果写的内容被放到一个网页上就可以了。
另外,如果您将url重定向到除webrequest可接受的url之外的任何其他url,则其他事件将无法拦截。因此,如果重定向到onbeforerequest中的对象url,则不会截获webrequest中的response headers阶段,但可以在xmlhttprequest的onreadystatechange事件中查看threm。
因此,结果是,响应头似乎无法修改,即使mdn web文档说这是可能的。而且,使用awebrequest stream filter来传输在客户端生成的或从indexeddb数据库提取的数据,而不是构建一个大型blob以供下载,这种想法行不通,因为无法拦截下载或更改响应头以触发下载,并通过stream filter将其写入。
不过,这是个有趣的主意。我仍然想知道,当数据被写在客户机上并以块或块的形式传递时,下载是否保持“开放”。也许,如果说明如何传递和接收数据的响应头的那一部分被修改了,它也会工作。
现在,我不再追求这种方法。其中一个web文档或一个bug记录指出,计划允许拦截数据url。也许,对于客户端的离线下载,这比假url更可取。
如果有人能用上这个,请告诉我们。谢谢您。