是否可以仅使用JavaScript将数据写入文件?


190

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

我引用了代码,但是它不起作用:给出错误:

未捕获的TypeError:非法构造函数

在铬和

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();
}

那么,我们是否可以仅使用Java脚本或不使用Java脚本将数据写入文件?



Answers:


89

有关此的一些建议-

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

27
HTML5 API的最大大小为5 mb。
起搏器

是的,不选择它就无法写入系统文件。阅读官方文档:w3.org/TR/file-upload/#security-discussion
Manoj Ghediya

216

您可以使用Blob和在浏览器中创建文件URL.createObjectURL。所有最近的浏览器都支持此功能

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

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;
  };

这是使用此技术从中保存任意文本的示例textarea

如果要立即启动下载而不是要求用户单击链接,则可以使用鼠标事件来模拟鼠标在链接上的单击,就像Lifecube回答一样。我创建了使用此技术的更新示例

  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);

1
@FirstBlood哪个部分不起作用,您遇到错误了吗?文件和链接的创建应在Safari 7+中运行(我相信如果您使用的前缀版本,则在Safari 6中也可以使用这些东西URL)。设置文件名在Safari中不起作用,因为它尚未实现download属性
没用的代码

1
我在Safari 5.1上尝试过它:)
First Blood

1
保存的文档中缺少新行字符
Benny

1
@Benny的换行符在那里。JS使用换行符\n来表示换行符,就像UNIX程序一样。您可能正在Windows程序(例如记事本)中查看它,该程序不会将\n字符呈现为新行。如果希望换行符在记事本和其他Windows程序中正确显示,请在将文本Blob替换为之前将其替换\n\r\ntext = text.replace(/\n/g, '\r\n')
无用的代码

2
@ user3241111不是,它应该可以工作。那样的东西并不是那么不寻常。我已经看到黑客的方法;-)过去,我还只是mouseover在链接上生成文件而已,但是取决于它正在执行的处理量可能并不理想。
无用的代码

41

如果您在谈论浏览器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');


惊人的生命立方。我确实需要该功能,尽管我不希望用户知道正在下载任何文件,但我希望对用户完全隐藏该文件,因为它可能会让用户不敢相信执行某些操作后会自动下载某些文件在网站上,尽管我们仅将其用于营销数据收集目的,但能否请您分享如何下载文件而不使用户可见?
Just_another_developer

1
上述解决方案有点过时了。您可能需要考虑html 5 javascript库。github.com/eligrey/FileSaver.js
Lifecube

@Lifecube使用FileSaver.js,有没有一种方法可以自动将文本保存到文件中而无需用户交互?谢谢!JS新手;所有的帮助表示赞赏
弥敦道

2
关于在用户不知道的情况下保存文件的几个问题:这种行为正是设计所避免的。这将打开一个易于使用的Pandora安全威胁的盒子。Cookies用于收集用于营销目的的数据。
阿里·奥科宁

请注意,在Windows 10上的firefox v76中,我无法以.html格式下载html文件。下载文件的末尾附加了.pdf。
CSchwarz

23

上面的答案很有用,但是,我找到了可以帮助您在单击按钮时直接下载文本文件的代码。在此代码中,您还可以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();
}

2
优秀的。在Opera上为我工作。除了需要用语句“ document.body.removeChild(event.target)”替换未知功能:“ destroyClickedElement”
steveOw

3
使用时需要小心createObjectURL。与JS中的大多数事物不同,当没有更多引用时,使用它创建的对象不会自动被垃圾回收;它们仅在页面关闭时被垃圾回收。由于未URL.revokeObjectURL()在此代码中使用释放上一次调用所使用的内存,因此存在内存泄漏;如果用户saveTextFile多次调用,他们将继续消耗越来越多的内存,因为您从未释放过它。
无用的代码,


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>


3

使用上面用户@ 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;
}

5
不知道为什么这被否决了。这个对我有用。不赞成投票的人至少应该对为什么不赞成投票发表评论!
RPM

5
我没有投票,但实际上不建议对投票发表评论。用户应该对帖子的内容发表评论,并对帖子的内容进行投票,但是他们不应该对自己的投票发表评论。如果某人投票而未发表评论,则可以根据投票数将其表示为“此答案有用”或“此答案无用”。

这不起作用。.它不会下载文件。它只是创建一个隐藏的iframe。我在chrome和firefox上进行了测试
NaiveCoder

2

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

创建链接的按钮和下载链接可以合并到一个链接中,因为链接元素可以具有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>

0

的,可能的代码是

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; 
}) 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.