是否可以流式传输在 javascript 中生成的八位字节流
Is it possible to stream an octet stream being generated in javascript?
假设一个案例,使用一些javascript逻辑从一个小字符串生成一个巨大的字符串,然后强制在浏览器上下载文本文件。
这可以通过将其作为href来使用八位字节流下载来实现,如本答案所述:
在内存中创建一个文件供用户下载,而不是通过服务器。
function download(filename, text) {
var pom = document.createElement('a');
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
pom.click();
}
但是这个解决方案要求在推送下载之前完全生成"文本",因此,它必须完全保存在浏览器中。
是否可以仅使用客户端逻辑在生成文本时流式传输文本?
例如:
var inputString = "A";
var outStr = "";
for(var i = 0; i < 10000000 ; i++)
{
/* concatenate inputString to output on the go */
}
Yes & No。不,因为没有办法只用客户端javascript写入文件。有点。您可以提示用户下载并保存文件,但如您所提到的,代码必须在下载发生之前生成整个文件。注意:通过"流",我假设你的意思是流到文件(不断写入文件(和"客户端逻辑",我假设你的意思是在浏览器中。
看起来Mozilla一直在研究一种让客户端代码与文件交互的方法。是的来了。有点。它们有自己的文件系统 api,可让您与本地计算机文件系统进行交互(写入(。具体来说,有一个函数可以让您将输入流写入文件。但是,有几个星号:
1(看起来整个系统都被弃用了;他们鼓励开发人员使用OS.file而不是File I/O
2(你必须使用XPConnect
,一个让你在javascript中访问Mozilla的XPCOM
(组件库(的系统。如果你想在浏览器中执行此操作,看起来只有 Firefox 扩展具有与这些组件交互的适当权限((。如果你不想在浏览器中这样做,你显然可以使用node。
当然,在实施过程中必然会出现更多的复杂情况。但这看起来是最确定的前进道路,看看OS.File
如何让你访问OS.File.writeAtomic()
和基本写入文件等功能。
话虽如此,这不是一条很好的道路,但希望这能给你一个坚实的起点。正如@dandavis提到的,浏览器(即"客户端逻辑"(被设计为不允许这种事情。如果一个网站可以与任何用户的本地文件系统进行交互,那将是一个非常巨大的监督/安全漏洞。
其他资源:
Wikipedia on XPConnect
在javascript中使用XPCOM的指南 - 可能不是那么有用
有一种方法可以做到这一点,但它依赖于仅限Chrome的文件系统API。我们将在沙盒文件系统中创建并写入一个临时文件,并在完成后将其复制到常规文件系统。这样,您就不必将整个文件存储在内存中。Chrome API的异步版本目前尚未被W3C考虑标准化,但同步版本(使用Web Workers(是。如果浏览器支持是一个问题,那么这个答案不适合你。
该 API 的工作方式如下:首先,我们从浏览器获取requestFileSystem()
函数。目前它以"webkit"为前缀:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
接下来,我们请求一个临时文件系统(这样我们就不需要请求用户权限(:
var fileSystem; //This will store the fileSystem for later access
var fileSize = 1024*1024 //Our maximum file system size.
function errorHandler(e) {
console.log('Error: ' + e.name);
}
window.requestFileSystem(window.TEMPORARY, fileSize, function (fs) { fileSystem = fs; }, errorHandler);
现在我们可以访问文件系统,是时候创建一个文件了:
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 不会保存到普通的用户文件系统中。相反,它会保存到一个特殊的沙盒文件夹中。如果要将其保存到用户的文件系统,可以创建filesystem:
链接。当用户单击它时,它会提示他们保存它。保存后,您可以删除临时文件。
此函数使用 fileEntry
的 toURL()
函数生成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>
这里有一个 plunker 来证明这一点:http://plnkr.co/edit/q6ihXWEXSOtutbEy1b5G?p=preview
希望这能实现您想要的。您可以连续附加到文件中,它不会保留在内存中,但它将保存在沙盒文件系统中,直到用户将其保存到常规文件系统。
有关更多信息,请查看这篇HTML5rocks文章,如果您想使用更新的同步Web Worker API,请查看这篇文章。
我会按照@quantumwannabe描述它的方式建议它,使用临时沙箱文件来附加块。
但是有一种新方法可以在今天使用(在标志后面(,但将在下一个版本的chrome中启用(52(
这就是我要让@KeenanLidral-波特回答不正确的地方。@quantumwannabe回答不必要的步骤
因为现在有一种方法可以直接将流写入文件系统:StreamSaver.js
它就像有一个服务器发送八位字节流标头,并告诉浏览器在服务工作者的帮助下下载数据块
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
- 简单的Javascript方式,在输入字段的每5位数字后添加一个空格
- Javascript 将 int 值转换为八位字节流数组
- 如何上传文件不使用多部分编码?(可能使用八位字节或其他什么)
- 将Uint8ClampedArray缓冲区作为字节流输出
- Java从浏览器读取字节流不同的正文长度
- 是否可以流式传输在 javascript 中生成的八位字节流
- 测试数组是否包含八个 3 键值中的任何一个 - 井字游戏
- 将 IP 地址拆分为八位字节,然后对每个八位字节进行一些数学运算
- 格式化输入字段,将前4位数字用句点分隔,将后2位数字用句号分隔
- 将base64中的图像发送到Web服务-'应用程序/八位字节流'不是预期的类型'text/xml
- 用于查询字符串的位字段
- 资源被解释为图像,但使用MIME类型的应用程序/八位字节流传输
- Javascript或Jquery-将输入字段限制为只有8位小数
- 如何验证电话字段仅接受8位数字(不小于和不大于)
- 将数字转换为完整二进制八位
- 使用Javascript输入字段需要8位数字
- 如何在密码字段显示4位数字
- 如何将Javascript字符串转换为八位字节/字符数组
- 为什么这个代码有超过4个字符的3个八位字节
- 解码可读字节流