是否可以对javascript中生成的八位字节流进行流式处理?

是否可以对javascript中生成的八位字节流进行流式处理?,javascript,Javascript,假设使用一些javascript逻辑从一个小字符串生成一个大字符串,然后强制在浏览器上下载文本文件 这可以使用八位字节流下载,将其作为href,如本答案中所述: 但该解决方案要求在推送下载之前完全生成“文本”, 因此,它必须完全保存在浏览器内存中 是否可以仅使用客户端逻辑在生成文本时对其进行流式处理 例如: var inputString = "A"; var outStr = ""; for(var i = 0; i < 10000000 ; i++) { /* concate

假设使用一些javascript逻辑从一个小字符串生成一个大字符串,然后强制在浏览器上下载文本文件

这可以使用八位字节流下载,将其作为href,如本答案中所述:

但该解决方案要求在推送下载之前完全生成“文本”, 因此,它必须完全保存在浏览器内存中

是否可以仅使用客户端逻辑在生成文本时对其进行流式处理

例如:

var inputString = "A";
var outStr = "";
for(var i = 0; i < 10000000 ; i++)
 {
   /* concatenate inputString to output on the go */
 }
var inputString=“A”;
var-outsr=“”;
对于(变量i=0;i<10000000;i++)
{
/*将inputString连接到运行中的输出*/
}

是&否。否,因为没有一种只使用客户端javascript写入文件的方法。有点。您可以提示用户下载并保存文件,但正如您所提到的,代码必须在下载之前生成整个文件。注意:这里的“流”是指流到文件(不断写入文件)&这里的“仅客户端逻辑”是指在浏览器中

看起来Mozilla一直在研究一种让客户端代码与文件交互的方法。是的。有点它们有自己的功能,允许您与本地计算机文件系统进行交互(写入)。具体来说,有一个函数可以让您。但是,有几个星号:

1) 看起来整个系统都被弃用了;它们鼓励开发人员通过文件I/O进行使用

2) 您必须使用一个系统,该系统允许您以javascript访问Mozilla的
XPCOM
(组件库)。如果您想在浏览器中执行此操作,那么看起来只有firefox扩展具有与这些组件交互的适当权限()。如果不想在浏览器中执行此操作,显然可以使用node

毫无疑问,在实施过程中必然会出现更多的复杂情况。但这看起来是最可靠的前进之路,因为
OS.File
可以让您访问&basic之类的函数

也就是说,这不是一条伟大的道路,但希望这能给你一个坚实的起点。正如@dandavis提到的,浏览器(即“客户端逻辑”)的设计不允许这种事情。如果一个网站可以与任何用户的本地文件系统进行交互,这将是一个巨大的监督/安全缺陷

其他资源:


-可能没有那么有用

有一种方法可以做到这一点,但它依赖于仅限Chrome的文件系统API。我们将在沙盒文件系统中创建并写入临时文件,并在完成后将其复制到常规文件系统。这样,您就不必将整个文件存储在内存中。W3C目前没有考虑对ChromeAPI的异步版本进行标准化,但同步verison(使用web workers)正在考虑。如果浏览器支持是一个问题,那么这个答案不适合您

API的工作原理如下: 首先,我们从浏览器中获取
requestFileSystem()
函数。目前它的前缀为“webkit”:

接下来,我们请求一个临时文件系统(这样我们就不需要请求用户权限):

现在我们可以访问文件系统,现在是创建文件的时候了:

var fileOptions = {
    create: true, //If the file is not found, create it
    exclusive: false //Don't throw an error if the file doesn't exist
};
这里我们调用
getFile()
函数,如果文件不存在,它可以创建一个文件。在回调内部,我们可以创建一个新的
fileWriter
,用于写入文件。然后将
fileWriter
移动到文件的末尾,我们创建一个新的文本blob以附加到它

fileSystem.root.getFile(fileName, fileOptions, function(fileEntry) {
    fileEntry.createWriter(function(fileWriter) {
      fileWriter.seek(fileWriter.length); 
      var blob = new Blob([STRING_TO_WRITE], {type: 'text/plain'});
      fileWriter.write(blob);
    }, errorHandler);
});
请注意,此API不会保存到普通的用户文件系统。相反,它会保存到一个特殊的沙盒文件夹中。如果要将其保存到用户的文件系统,可以创建
文件系统:
链接。当用户单击它时,它将提示他们保存它。保存后,您可以删除临时文件

此函数使用
fileEntry
tour()函数生成
filesystem
链接:

var save = function () {
  var download = document.querySelector("a[download]");
  if (!fileSystem) { return; }
   fileSystem.root.getFile(fileName, {create: false, exclusive: true}, function(fileEntry) {
    download.href = fileEntry.toURL();
  }, errorHandler);
}
使用具有下载属性的链接将强制下载文件

<a download></a>

希望这能实现你想要的。您可以连续地附加到文件中,它不会保留在内存中,但它将位于沙盒文件系统中,直到用户将其保存到常规文件系统中


有关更多信息,请查看此功能,或者如果您想使用更新的同步Web Worker API。

我建议使用@quantumwannabe的方式,使用临时沙盒文件来附加块

但是现在有一种新的方式可以使用(在旗帜后面),但将在下一版本的chrome(52)中启用

这就是我要让@KeenanLidral Porter回答不正确的地方。和@quantumwannabe回答不必要的步骤
因为现在有一种直接将流写入文件系统的方法:

它的作用就像有一个服务器发送八位字节流头,并告诉浏览器在服务人员的帮助下下载数据块

const writeStream = streamSaver.createWriteStream('filename.txt')
const encoder = new TextEncoder
let data = 'a'.repeat(1024) // Writing some stuff triggers the save dialog to show
let uint8array = encoder.encode(data + "\n\n")

writeStream.write(uint8array) // Write some data when you got some
writeStream.close() // End the saving

如果您没有找到这个问题的解决方案,那么可以将数据放入一个文件夹中,然后使用它生成下载链接。浏览器可能会将数据缓存在磁盘上,尤其是您不会有大的数据URL。@Phillip我不想将所有内容存储到blob或zip文件中,也不想使用indexDb,流媒体是必需的。否。所有当前的浏览器技术都要求在发送第一个字节之前知道总体大小;只有node.js等较新的服务器端工具才能使用http1.1分块。您将不得不使用许多连接或缓冲区。您可能可以使用WebSocket,但这需要在两端进行一些自定义。请发布该库工作原理的解释,以及它所使用的API的特定代码,而不仅仅是github链接。@Infrast
ReadableStream
var save = function () {
  var download = document.querySelector("a[download]");
  if (!fileSystem) { return; }
   fileSystem.root.getFile(fileName, {create: false, exclusive: true}, function(fileEntry) {
    download.href = fileEntry.toURL();
  }, errorHandler);
}
<a download></a>
const writeStream = streamSaver.createWriteStream('filename.txt')
const encoder = new TextEncoder
let data = 'a'.repeat(1024) // Writing some stuff triggers the save dialog to show
let uint8array = encoder.encode(data + "\n\n")

writeStream.write(uint8array) // Write some data when you got some
writeStream.close() // End the saving