使用 HTML5/JavaScript 生成并保存文件

IT技术 javascript html download
2021-02-01 01:29:28

我最近一直在摆弄 WebGL,并且让 Collada 阅读器开始工作。问题是它很慢(Collada 是一种非常冗长的格式),所以我将开始将文件转换为更易于使用的格式(可能是 JSON)。我已经有了用 JavaScript 解析文件的代码,所以我也可以将它用作我的导出器!问题是节省。

现在,我知道我可以解析文件,将结果发送到服务器,并让浏览器从服务器请求文件作为下载。但实际上服务器与这个特定的过程无关,那么为什么要涉及它呢?我已经在内存中拥有所需文件的内容。有什么方法可以使用纯 JavaScript 向用户展示下载内容?(我对此表示怀疑,但不妨问一下……)

需要明确的是:我不会在用户不知情的情况下尝试访问文件系统!用户将提供一个文件(可能通过拖放),脚本将在内存中转换文件,并提示用户下载结果。就浏览器而言,所有这些都应该是“安全”的活动。

[编辑]:我没有预先提到它,所以回答“Flash”的海报已经足够有效了,但我正在做的部分工作是试图强调纯 HTML5 可以做什么......所以 Flash 是就我而言。(尽管对于任何人做“真正的”网络应用程序来说,这是一个完全有效的答案。)在这种情况下,除非我想涉及服务器,否则看起来我很不走运。不管怎么说,还是要谢谢你!

6个回答

适用于 HTML5 浏览器的简单解决方案...

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    }
    else {
        pom.click();
    }
}

用法

download('test.txt', 'Hello world!');
如果您知道要下载的源 url,这是最好的解决方案!
2021-03-12 01:29:28
我有 Chrom 42.0.2311.90 ,这对我来说是预期的文件名。
2021-03-12 01:29:28
可以包含的数据量是否有限制?
2021-03-21 01:29:28
这种方法在 Chrome 中一直有效,直到我几天前收到的最新更新 (35.0.1916.114 m)。现在它部分起作用,因为文件名和扩展名不再起作用(它总是命名文件 download.txt,不管传递的是什么。)
2021-04-01 01:29:28
设置文件名的能力使其成为赢家。
2021-04-08 01:29:28

好的,创建一个 data:URI 对我来说绝对有用,感谢 Matthew 和 Dennkster 指出了这个选项!这基本上是我如何做到的:

1) 将所有内容放入一个名为“content”的字符串中(例如,通过最初在那里创建它或通过读取已构建页面的标记的innerHTML)。

2)构建数据URI:

uriContent = "data:application/octet-stream," + encodeURIComponent(content);

根据浏览器类型等会有长度限制,但例如 Firefox 3.6.12 至少可以工作到 256k。在 Base64 中编码而不是使用 encodeURIComponent 可能会使事情更高效,但对我来说这没问题。

3) 打开一个新窗口并将其“重定向”到这个 URI 提示我的 JavaScript 生成页面的下载位置:

newWindow = window.open(uriContent, 'neuesDokument');

就是这样。

我认为我们正在使这变得比需要的更困难。在此页面上打开您的 JS 控制台并将其放入location.href = "data:application/octet-stream," + encodeURIComponent(jQuery('#answer-4551467 .post-text').first().text());,它会将@Nøk 的答案的内容保存到一个文件中。我没有 IE 来测试它,但它适用于 webkit。
2021-03-11 01:29:28
嗨,我试过这个,但它下载文件为 .part 文件。如何设置文件类型?
2021-03-18 01:29:28
如果您想避免使用可能被阻止的弹出窗口,您可以将 设置location.href为内容。location.href = uriContent.
2021-03-22 01:29:28
@SedatBaşar 数据 URI 不支持设置文件名,您必须依靠浏览器使用 mime 类型设置适当的扩展名。但是如果浏览器可以呈现 mime 类型,它就不会下载它,但会显示它。还有其他一些方法可以做到这一点,但都不适用于 IE<10。
2021-04-01 01:29:28
IE 并不真正支持数据 URI,Firefox 似乎以随机名称保存文件。
2021-04-05 01:29:28

HTML5 定义了一个window.saveAs(blob, filename)方法。目前任何浏览器都不支持它。但是有一个名为FileSaver.js的兼容性库,可以将此功能添加到大多数现代浏览器(包括 Internet Explorer 10+)。Internet Explorer 10 支持一种navigator.msSaveBlob(blob, filename)方法 ( MSDN ),该方法在 FileSaver.js 中用于 Internet Explorer 支持。

我写了一篇博客文章,其中包含有关此问题的更多详细信息。

阻止弹出窗口怎么样?该库的行为类似于@Nøk 的解决方案。Firefox 中的纯文本以新方式打开。只有 Chrome 会尝试保存它,但它会更改扩展名(我需要一个没有扩展名的点文件)。
2021-03-13 01:29:28
FileSaver.js 现在支持 IE
2021-03-19 01:29:28
@ciembor 啊哈,如果直接点击,则不会阻止弹出窗口。
2021-03-24 01:29:28
W3C 表示:该文档的工作已停止,不应作为参考或用作实施的基础。
2021-04-06 01:29:28
@ciembor (object url+)download 属性变体(我与 chrome 一起使用)允许您设置文件名。它在 chrome 中对我有用。
2021-04-08 01:29:28

保存大文件

长数据 URI 可能会给浏览器带来性能问题。保存客户端生成的文件的另一种选择是将它们的内容放在 Blob(或文件)对象中,并使用URL.createObjectURL(blob). 这将返回一个可用于检索 blob 内容的 URL。blob 存储在浏览器中,直到URL.revokeObjectURL()在 URL 上调用或关闭创建它的文档。大多数网络浏览器都支持对象 URL,Opera Mini 是唯一不支持它们的浏览器。

强制下载

如果数据是文本或图像,浏览器可以打开文件,而不是将其保存到磁盘。要在单击链接时下载文件,您可以使用该download属性。然而,并不是所有的浏览器都支持下载属性另一种选择是application/octet-stream用作文件的 MIME 类型,但这会导致文件显示为二进制 blob,如果您不指定或不能指定文件名,这对用户尤其不友好。另请参阅“强制打开“另存为...”弹出窗口,在文本链接单击 HTML 中pdf 时打开

指定文件名

如果 blob 是使用 File 构造函数创建的,您还可以设置文件名,但只有少数 Web 浏览器(包括 Chrome 和 Firefox)支持 File 构造函数文件名也可以指定为download属性的参数,但这要考虑很多安全因素Internet Explorer 10 和 11 提供了自己的方法msSaveBlob来指定文件名。

示例代码

var file;
var data = [];
data.push("This is a test\n");
data.push("Of creating a file\n");
data.push("In a browser\n");
var properties = {type: 'text/plain'}; // Specify the file's mime-type.
try {
  // Specify the filename using the File constructor, but ...
  file = new File(data, "file.txt", properties);
} catch (e) {
  // ... fall back to the Blob constructor if that isn't supported.
  file = new Blob(data, properties);
}
var url = URL.createObjectURL(file);
document.getElementById('link').href = url;
<a id="link" target="_blank" download="file.txt">Download</a>

2021-03-14 01:29:28
@Calvin:我已经更新了答案以解释如何强制下载并提供文件名。对于IE,相信可以使用msSaveBlob打开“另存为”对话框。对于其他浏览器,您唯一的选择是从下载链接的上下文菜单中手动选择“另存为”。
2021-03-19 01:29:28
@Jek-fdrv:只有 Blob-url 在 Safari 中有效。Safari 不支持下载属性和文件构造函数,因此您无法强制下载,这意味着 blob 可能会在浏览器本身中打开,并且您无法指定文件名。对于给定的示例,您应该仍然可以使用 Safari 使用链接的上下文菜单下载文件。
2021-03-27 01:29:28
这是一个非常有帮助和信息丰富的答案。另一件事可以帮助像我这样的人:在设置之后document.getElementById('link').href = url;,您的代码可以继续使用元素的.click()方法来触发链接
2021-03-29 01:29:28
我可以显示一个对话框(弹出)来指定一个文件夹(目录)来保存文件吗?
2021-04-01 01:29:28
function download(content, filename, contentType)
{
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}
与@Matěj Pokorný 的回答不同,即使在最新的 Chrome 中也能正常工作。谢谢。
2021-03-13 01:29:28
contentType 的作用是什么?它是干什么用的?
2021-03-14 01:29:28
这在 FF36 或 IE11 上对我不起作用。如果我a.click使用document.createEvent()Matěj Pokorný 建议的代码替换,它适用于 FF 但不适用于 IE。我没试过Chrome。
2021-03-28 01:29:28