【问题标题】:Is it possible to write data to file using only JavaScript?是否可以仅使用 JavaScript 将数据写入文件?
【发布时间】:2014-01-27 13:16:06
【问题描述】:

我想使用 JavaScript 将数据写入现有文件。 我不想在控制台上打印它。 我想实际将数据写入abc.txt。 我阅读了许多已回答的问题,但他们在控制台上打印的每个地方。 在某些地方,他们已经给出了代码,但它不起作用。 所以请任何人帮助我如何实际将数据写入文件。

我参考了代码,但它不起作用: 它的错误:

未捕获的类型错误:非法构造函数

在铬和

SecurityError: 操作不安全。

在 Mozilla 上

var f = "sometextfile.txt";

writeTextFile(f, "Spoon")
writeTextFile(f, "Cheese monkey")
writeTextFile(f, "Onion")

function writeTextFile(afilename, output)
{
  var txtFile =new File(afilename);
  txtFile.writeln(output);
  txtFile.close();
}

那么我们真的可以仅使用 Javascript 或不使用 Javascript 将数据写入文件吗?

【问题讨论】:

标签: javascript html


【解决方案1】:

您可以使用BlobURL.createObjectURL 在浏览器中创建文件。所有最近的浏览器support this

您不能直接保存您创建的文件,因为这会导致严重的安全问题,但您可以将其作为下载链接提供给用户。在支持下载属性的浏览器中,您可以通过链接的download attribute 建议文件名。与任何其他下载一样,下载文件的用户将对文件名拥有最终决定权。

var textFile = null,
  makeTextFile = function (text) {
    var data = new Blob([text], {type: 'text/plain'});

    // If we are replacing a previously generated file we need to
    // manually revoke the object URL to avoid memory leaks.
    if (textFile !== null) {
      window.URL.revokeObjectURL(textFile);
    }

    textFile = window.URL.createObjectURL(data);

    // returns a URL you can use as a href
    return textFile;
  };

这是一个example,它使用这种技术从textarea 保存任意文本。

如果您想立即启动下载而不是要求用户点击链接,您可以使用鼠标事件来模拟鼠标点击链接,就像Lifecubeanswer 所做的那样。我创建了一个使用这种技术的updated example

  var create = document.getElementById('create'),
    textbox = document.getElementById('textbox');

  create.addEventListener('click', function () {
    var link = document.createElement('a');
    link.setAttribute('download', 'info.txt');
    link.href = makeTextFile(textbox.value);
    document.body.appendChild(link);

    // wait for the link to be added to the document
    window.requestAnimationFrame(function () {
      var event = new MouseEvent('click');
      link.dispatchEvent(event);
      document.body.removeChild(link);
    });

  }, false);

【讨论】:

  • @FirstBlood 哪个部分不工作,您是否遇到错误?文件和链接创建should work in Safari 7+(如果您使用URL 的前缀版本,我相信这些东西也应该可以在Safari 6 中使用)。设置文件名在 Safari 中不起作用,因为它还没有实现 download attribute
  • 我在 Safari 5.1 上尝试过 :)
  • 保存的文档中缺少换行符
  • @Benny 换行符在那里。 JS 像 UNIX 程序一样使用换行符 \n 来表示新行。您可能正在 Windows 程序中查看它,例如记事本,which does not render the \n character as a new line。如果您希望在记事本和其他一些 Windows 程序中正确呈现换行符,请在将文本放入 Blob 之前将每个 \n 替换为 \r\ntext = text.replace(/\n/g, '\r\n')
  • @user3241111 不是真的,它应该可以工作。像这样的事情并不是那么不寻常。我已经看到了更骇人听闻的做法;-) 过去,我也只是在链接上的mouseover 上生成文件,但取决于它正在执行的处理量,这可能效果不佳。
【解决方案2】:

对此的一些建议 -

  1. 如果您尝试在客户端计算机上写入文件,则不能以任何跨浏览器方式执行此操作。 IE 确实具有启用“受信任”应用程序以使用 ActiveX 对象来读取/写入文件的方法。
  2. 如果您尝试将其保存在您的服务器上,那么只需将文本数据传递到您的服务器并使用某种服务器端语言执行文件编写代码。
  3. 要在客户端存储一些非常小的信息,您可以使用 cookie。
  4. 使用 HTML5 API 进行本地存储。

【讨论】:

  • HTML5 API 的最大值仅为 5 mb。
  • 是的,你不能不选择它就写入系统文件。阅读官方文档:w3.org/TR/file-upload/#security-discussion
  • 您能解释一下第 2 点吗?“如果您尝试将其保存在您的服务器上,那么只需将文本数据传递到您的服务器并使用某种服务器端语言执行文件编写代码。”能给个链接教程吗?
  • @s1w_ 它非常不言自明,因为文本数据(来自客户端)创建/附加到服务器端的文件。即在服务器端编写文件代码。
【解决方案3】:

如果您在谈论浏览器 javascript,出于安全原因,您不能将数据直接写入本地文件。 HTML 5 新 API 只能让你读取文件。

但是如果你想写入数据,并让用户以文件的形式下载到本地。以下代码有效:

    function download(strData, strFileName, strMimeType) {
    var D = document,
        A = arguments,
        a = D.createElement("a"),
        d = A[0],
        n = A[1],
        t = A[2] || "text/plain";

    //build download link:
    a.href = "data:" + strMimeType + "charset=utf-8," + escape(strData);


    if (window.MSBlobBuilder) { // IE10
        var bb = new MSBlobBuilder();
        bb.append(strData);
        return navigator.msSaveBlob(bb, strFileName);
    } /* end if(window.MSBlobBuilder) */



    if ('download' in a) { //FF20, CH19
        a.setAttribute("download", n);
        a.innerHTML = "downloading...";
        D.body.appendChild(a);
        setTimeout(function() {
            var e = D.createEvent("MouseEvents");
            e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            a.dispatchEvent(e);
            D.body.removeChild(a);
        }, 66);
        return true;
    }; /* end if('download' in a) */



    //do iframe dataURL download: (older W3)
    var f = D.createElement("iframe");
    D.body.appendChild(f);
    f.src = "data:" + (A[2] ? A[2] : "application/octet-stream") + (window.btoa ? ";base64" : "") + "," + (window.btoa ? window.btoa : escape)(strData);
    setTimeout(function() {
        D.body.removeChild(f);
    }, 333);
    return true;
}

使用它:

download('the content of the file', 'filename.txt', 'text/plain');

【讨论】:

  • 上述解决方案有点过时了。您可能需要考虑 html 5 javascript 库。 github.com/eligrey/FileSaver.js
  • @Lifecube 使用 FileSaver.js,有没有办法在没有用户交互的情况下自动将文本保存到文件中?谢谢! JS新手;感谢您的所有帮助
  • 关于在用户不知情的情况下保存文件的几个问题:这种行为正是设计所避免的。这将打开一个易于使用的安全威胁的潘多拉盒子。 Cookie 用于为营销目的收集数据。
  • 请注意,我无法在 Windows 10 上的 firefox v76 中将 html 文件下载为 .html。下载的末尾附加了 .pdf。
  • 只是另一个开发者在讽刺吗?
【解决方案4】:

试试

let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent("My DATA");
a.download = 'abc.txt';
a.click();

如果你想下载二进制数据看here

更新

2020.06.14 我将 Chrome 升级到 83.0 及更高版本所以 sn-p 停止工作(原因:sandbox security 限制) - 但 JSFiddle 版本工作 - here

【讨论】:

    【解决方案5】:

    以上答案很有用,但是I found code 可以帮助您在单击按钮时直接下载文本文件。 在此代码中,您还可以根据需要更改 filename。它是带有 HTML5 的纯 javascript 函数。 为我工作!

    function saveTextAsFile()
    {
        var textToWrite = document.getElementById("inputTextToSave").value;
        var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
        var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
          var downloadLink = document.createElement("a");
        downloadLink.download = fileNameToSaveAs;
        downloadLink.innerHTML = "Download File";
        if (window.webkitURL != null)
        {
            // Chrome allows the link to be clicked
            // without actually adding it to the DOM.
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else
        {
            // Firefox requires the link to be added to the DOM
            // before it can be clicked.
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = destroyClickedElement;
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
    
        downloadLink.click();
    }
    

    【讨论】:

    • 优秀。在 Opera 上为我工作。除了需要用语句“document.body.removeChild(event.target)”替换未知函数:“destroyClickedElement”
    • 在使用createObjectURL时需要小心。与 JS 中的大多数东西不同,您使用它创建的对象不会在不再引用它们时自动被垃圾收集;它们仅在页面关闭时被垃圾收集。由于您没有在此代码中使用URL.revokeObjectURL() 来释放上次调用使用的内存,因此存在内存泄漏;如果用户多次调用saveTextFile,他们将继续消耗越来越多的内存,因为你从未释放它。
    • 您好,我不是网络开发人员,所以,首先感谢您的代码,它看起来很棒,但我不适合我。我尝试添加<form onsubmit="saveTextAsFile()"> 然后我的表单,并且我更改了downloadLink.download =“/home/myuser/myfile.txt”,但它没有创建任何东西。有什么帮助吗?谢谢
    【解决方案6】:

    如果无法使用新的Blob 解决方案,这肯定是现代浏览器中的最佳解决方案,仍然可以使用这种更简单的方法,它对文件大小有限制方式:

    function download() {
                    var fileContents=JSON.stringify(jsonObject, null, 2);
                    var fileName= "data.json";
    
                    var pp = document.createElement('a');
                    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
                    pp.setAttribute('download', fileName);
                    pp.click();
                }
                setTimeout(function() {download()}, 500);
    

    $('#download').on("click", function() {
      function download() {
        var jsonObject = {
          "name": "John",
          "age": 31,
          "city": "New York"
        };
        var fileContents = JSON.stringify(jsonObject, null, 2);
        var fileName = "data.json";
    
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.click();
      }
      setTimeout(function() {
        download()
      }, 500);
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="download">Download me</button>

    【讨论】:

      【解决方案7】:
      const data = {name: 'Ronn', age: 27};              //sample json
      const a = document.createElement('a');
      const blob = new Blob([JSON.stringify(data)]);
      a.href = URL.createObjectURL(blob);
      a.download = 'sample-profile';                     //filename to download
      a.click();
      

      在此处查看 Blob 文档 - Blob MDN 以提供文件类型的额外参数。默认情况下会生成 .txt 文件

      【讨论】:

        【解决方案8】:

        使用上面用户@useless-code (https://stackoverflow.com/a/21016088/327386) 的代码来生成文件。 如果你想自动下载文件,把刚才生成的textFile传给这个函数:

        var downloadFile = function downloadURL(url) {
            var hiddenIFrameID = 'hiddenDownloader',
            iframe = document.getElementById(hiddenIFrameID);
            if (iframe === null) {
                iframe = document.createElement('iframe');
                iframe.id = hiddenIFrameID;
                iframe.style.display = 'none';
                document.body.appendChild(iframe);
            }
            iframe.src = url;
        }
        

        【讨论】:

        • 不知道为什么这被否决了。这个对我有用。投反对票的人至少应该就为什么投反对票发表评论!
        • 我没有投反对票,但实际上直接不鼓励评论投票。用户应该对帖子的内容发表评论,并对帖子的内容进行投票,但他们不应该对自己的投票发表评论。如果有人在没有评论的情况下投票,您可以根据投票情况将其表示为“此答案有用”或“此答案无用”。
        • 这不起作用..它不下载文件。它只是创建一个隐藏的 iframe。我在 chrome 和 firefox 上测试过
        【解决方案9】:

        我在这里找到了很好的答案,但也找到了更简单的方法。

        用于创建 blob 的按钮和下载链接可以组合在一个链接中,因为链接元素可以具有 onclick 属性。 (反过来似乎是不可能的,给按钮添加一个href是行不通的。)

        您可以使用bootstrap 将链接设置为按钮样式,这仍然是纯javascript,除了样式。

        将按钮和下载链接结合起来还可以减少代码,因为需要更少的那些丑陋的getElementById 调用。

        这个例子只需要一个按钮来创建文本块并下载它:

        <a id="a_btn_writetofile" download="info.txt" href="#" class="btn btn-primary" 
           onclick="exportFile('This is some dummy data.\nAnd some more dummy data.\n', 'a_btn_writetofile')"
        >
           Write To File
        </a>
        
        <script>
            // URL pointing to the Blob with the file contents
            var objUrl = null;
            // create the blob with file content, and attach the URL to the downloadlink; 
            // NB: link must have the download attribute
            // this method can go to your library
            function exportFile(fileContent, downloadLinkId) {
                // revoke the old object URL to avoid memory leaks.
                if (objUrl !== null) {
                    window.URL.revokeObjectURL(objUrl);
                }
                // create the object that contains the file data and that can be referred to with a URL
                var data = new Blob([fileContent], { type: 'text/plain' });
                objUrl = window.URL.createObjectURL(data);
                // attach the object to the download link (styled as button)
                var downloadLinkButton = document.getElementById(downloadLinkId);
                downloadLinkButton.href = objUrl;
            };
        </script>
        

        【讨论】:

        • 被卡巴斯基阻止 :(
        • @Lokinou Security uber alles,但你也知道它被屏蔽的原因吗?
        • 我的猜测是阻止不需要的文件在没有用户操作的情况下被下载。
        【解决方案10】:

        是的有可能 代码在这里

        const fs = require('fs') 
        let data = "Learning how to write in a file."
        fs.writeFile('Output.txt', data, (err) => { 
              
            // In case of a error throw err. 
            if (err) throw err; 
        }) 

        【讨论】:

        • fs 是一个节点模块,我的意思是服务器端。我相信 OP 要求的是 JS 客户端?
        猜你喜欢
        • 1970-01-01
        • 2020-08-08
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-12
        • 1970-01-01
        • 2013-06-29
        • 1970-01-01
        相关资源
        最近更新 更多