使用 JavaScript 创建和保存文件 [duplicate]

Create and save a file with JavaScript [duplicate]

提问人:user1756980 提问时间:11/16/2012 最后编辑:isherwooduser1756980 更新时间:3/31/2022 访问量:994008

问:

我有要写入文件的数据,并打开一个文件对话框供用户选择保存文件的位置。如果它适用于所有浏览器,那就太好了,但它必须在 Chrome 中运行。我想在客户端完成所有操作。

基本上我想知道在这个函数中放什么:

saveFile: function(data)
{
}

函数接收数据的位置,让用户选择保存文件的位置,并在该位置使用该数据创建文件。

如果有帮助的话,使用 HTML 也可以。

“JavaScript 文件 ”对话框 保存

评论

7赞 Dan Dascalescu 11/8/2016
多年来一直与“在内存中创建文件”的精确副本,供用户下载,而不是通过服务器下载

答:

5赞 Aamir 11/16/2012 #1

你不能纯粹在 Javascript 中做到这一点。由于安全原因,在浏览器上运行的 Javascript 还没有足够的权限(已经有提案)。

相反,我建议使用 Downloadify

一个小型的 javascript + Flash 库,无需服务器交互即可创建和下载文本文件。

您可以在此处查看一个简单的演示,您可以在其中提供内容并测试保存/取消/错误处理功能。

评论

0赞 Joshua 10/7/2023
过时的答案
16赞 pdjota 11/16/2012 #2

对于最新的浏览器,如 Chrome,您可以使用文件 API,如本教程所示

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, saveFile, errorHandler);

评论

2赞 Fabrício Matté 11/16/2012
我认为这个代码片段会更接近提问者的意图。
2赞 voidstate 9/30/2014
请看这里,看看它死气沉沉的证据:lists.w3.org/Archives/Public/public-webapps/2014AprJun/......
42赞 Matt Greer 11/16/2012 #3

在创建文件之前,无法选择保存文件的位置。但是,至少在 Chrome 中,仅使用 JavaScript 生成文件是可能的。这是我创建CSV文件的旧示例。系统将提示用户下载它。不幸的是,这在其他浏览器中效果不佳,尤其是 IE。

<!DOCTYPE html>
<html>
<head>
    <title>JS CSV</title>
</head>
<body>
    <button id="b">export to CSV</button>
    <script type="text/javascript">
        function exportToCsv() {
            var myCsv = "Col1,Col2,Col3\nval1,val2,val3";

            window.open('data:text/csv;charset=utf-8,' + escape(myCsv));
        }

        var button = document.getElementById('b');
        button.addEventListener('click', exportToCsv);
    </script>
</body>
</html>

评论

1赞 user1756980 11/16/2012
当我使用它时,它会打开一个包含文本的新选项卡,它不会打开文件对话框窗口。
0赞 Jesse Chisholm 7/23/2014
@user1756980 - 是的。您需要从该新选项卡“保存到文件”。
0赞 Matt Greer 7/23/2014
这取决于浏览器、操作系统等。在我写答案的时候,Chrome 中的 csv 数据 url 会弹出一个保存对话框
1赞 Awesomeness01 3/30/2015
@JesseChisholm你可以在 JavaScript 中做到这一点。只需在变量中创建一个锚标记并将下载属性放在其上(如下所示:A.download = “下载名称.txt”),然后使用 A.click() 单击它。
156赞 Awesomeness01 3/30/2015 #4

function download(text, name, type) {
  var a = document.getElementById("a");
  var file = new Blob([text], {type: type});
  a.href = URL.createObjectURL(file);
  a.download = name;
}
<a href="" id="a">click here to download your file</a>
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>

然后,您可以通过将 download 属性放在锚标记上来下载文件。

我之所以喜欢这个比创建数据 url 更好,是因为你不必做一个大的长 url,你可以只生成一个临时 url。

评论

0赞 1/21/2016
@Banjocat 您应该检查浏览器是否支持某些对象。检测示例:否则,您只需更改下载方法或注意浏览器不支持下载文件所需的对象。if("URL"in window&&"createObjectURL"in URL&&"download"in Element.prototype)
1赞 aamarks 4/28/2018
在 firefox 中,如果您单击链接,这有效,但如果您右键单击并选择将链接另存为...什么也没发生。
1赞 posfan12 12/26/2020
在 Google Chrome 中不起作用:Download is disallowed. The frame initiating or instantiating the download is sandboxed, but the flag ‘allow-downloads’ is not set. See https://www.chromestatus.com/feature/5706745674465280 for more details.
0赞 Awesomeness01 12/28/2020
@posfan12 尝试在您自己的页面中实现它,SO 将代码片段呈现在 iframe 中,不允许在没有 allow-downloads 标志的情况下下载文件。
10赞 Netsi1964 4/11/2015 #5

在控制台中尝试过这个,它有效。

var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob
window.open(URL.createObjectURL(oMyBlob));
340赞 Kanchu 6/15/2015 #6

Awesomeness01 对代码进行了非常小的改进(不需要锚标记),并按照 trueimage(支持 IE)的建议进行了添加:

// Function to download data to a file
function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) // IE10+
        window.navigator.msSaveOrOpenBlob(file, filename);
    else { // Others
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}

经测试,可在 Chrome、FireFox 和 IE10 中正常工作。

在Safari中,数据会在新选项卡中打开,并且必须手动保存此文件。

评论

1赞 Aaron Yarborough 2/8/2016
具体来说,IE是哪个版本?
1赞 trueimage 8/25/2016
这在 IE 11.0.9600.18426 中不起作用,但在 Chrome 52.0.2743.116 m 中不起作用。有什么想法可以在 IE 11 中工作吗?
1赞 Andrew Willems 1/23/2017
在我看来应该在分支中,否则 IE10+ 将创建但不会删除锚 () 元素。var a = document.createElement("a")else<a>
2赞 Bravo Yeung 6/4/2019
下载时如何在此脚本中设置位置?
2赞 posfan12 12/26/2020
我们可以用什么来做什么?type
3赞 We B Martians 2/22/2018 #7

对于 Chrome 和 Firefox,我一直在使用纯 JavaScript 方法。

(我的应用程序无法使用软件包,例如,它是由一个特殊的引擎提供的:一个 DSP,里面塞满了 WWWeb 服务器,几乎没有空间容纳任何东西。Blob.js

function FileSave(sourceText, fileIdentity) {
    var workElement = document.createElement("a");
    if ('download' in workElement) {
        workElement.href = "data:" + 'text/plain' + "charset=utf-8," + escape(sourceText);
        workElement.setAttribute("download", fileIdentity);
        document.body.appendChild(workElement);
        var eventMouse = document.createEvent("MouseEvents");
        eventMouse.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        workElement.dispatchEvent(eventMouse);
        document.body.removeChild(workElement);
    } else throw 'File saving not supported for this browser';
}

注释、警告和黄鼠狼词:

  • 我在 Linux (Maipo) 和 Windows(7 和 10)环境中运行的 Chrome 和 Firefox 客户端中都成功地使用了此代码。
  • 但是,如果大于 MB,Chrome 有时会(仅有时)卡在自己的下载中,没有任何故障指示;到目前为止,Firefox还没有表现出这种行为。原因可能是 Chrome 中的某些 blob 限制。坦率地说,我只是不知道;如果有人有任何想法如何纠正(或至少检测),请发布。如果发生下载异常,当 Chrome 浏览器关闭时,它会生成诊断,例如sourceTextChrome browser diagnostic
  • 此代码与 Edge 或 Internet Explorer 不兼容;我没有尝试过 Opera 或 Safari。
4赞 Endless 6/1/2019 #8

StreamSaver 是一种保存非常大的文件的替代方法,而无需将所有数据保留在内存中。
事实上,它模拟了服务器在保存文件时的所有内容,但所有客户端都与服务工作者一起模拟。

您可以获取编写器并手动将 Uint8Array 写入其中,也可以将二进制 readableStream 通过管道传输到可写流

下面举几个例子说明:

  • 如何将多个文件保存为 zip
  • 将 readableStream 从 例如 或 管道传输到 StreamSaverResponseblob.stream()
  • 键入内容时手动写入可写流
  • 或重新编码视频/音频

下面是一个最简单形式的示例:

const fileStream = streamSaver.createWriteStream('filename.txt')

new Response('StreamSaver is awesome').body
  .pipeTo(fileStream)
  .then(success, error)

如果要保存 Blob,只需将其转换为 readableStream 即可

new Response(blob).body.pipeTo(...) // response hack
blob.stream().pipeTo(...) // feature reference

评论

0赞 lovasoa 8/25/2019
这看起来是一个非常有用的库。谢谢!
11赞 user12066722 10/13/2019 #9
function SaveBlobAs(blob, file_name) {
    if (typeof navigator.msSaveBlob == "function")
        return navigator.msSaveBlob(blob, file_name);

    var saver = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
    var blobURL = saver.href = URL.createObjectURL(blob), 
        body = document.body;

    saver.download = file_name;

    body.appendChild(saver);
    saver.dispatchEvent(new MouseEvent("click"));
    body.removeChild(saver);
    URL.revokeObjectURL(blobURL);
}