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

IT技术 javascript html
2021-01-24 06:11:40

我想使用 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 将数据写入文件吗?

6个回答

您可以使用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);
@ user3241111 不是真的,它应该可以工作。像这样的事情并不是那么不寻常。我见过黑客的做法 ;-) 过去我也只mouseover在链接上生成文件,但取决于它正在执行的处理量,这可能效果不佳。
2021-03-13 06:11:40
@FirstBlood 哪个部分不起作用,您收到错误了吗?文件和链接创建应该在 Safari 7+ 中工作(如果你使用 的前缀版本,我相信这些东西也应该在 Safari 6 中工作URL)。设置文件名在 Safari 中不起作用,因为它还没有实现download属性
2021-03-17 06:11:40
保存的文档中缺少换行符
2021-03-18 06:11:40
@Benny 换行符在那里。JS 使用换行符\n来表示新行,就像 UNIX 程序一样。您可能正在 Windows 程序(例如记事本)中查看它,该程序不会将\n字符呈现为新行如果你想新行被正确地渲染在记事本和其他一些Windows程序,把文成之前Blob替换每个\n\r\ntext = text.replace(/\n/g, '\r\n')
2021-04-05 06:11:40
我在 Safari 5.1 上尝试过 :)
2021-04-07 06:11:40

对此的一些建议 -

  1. 如果您尝试在客户端计算机上编写文件,则不能以任何跨浏览器的方式执行此操作。IE 确实有方法使“受信任的”应用程序能够使用 ActiveX 对象来读/写文件。
  2. 如果您尝试将其保存在您的服务器上,那么只需将文本数据传递到您的服务器并使用某种服务器端语言执行文件编写代码。
  3. 要在客户端存储一些相当小的信息,您可以使用 cookie。
  4. 使用 HTML5 API 进行本地存储。
@s1w_ 考虑到文本数据(来自客户端)创建/附加到服务器端的文件,这是不言自明的。即在服务器端编写文件代码。
2021-03-10 06:11:40
你能解释第 2 点吗?“如果你想把它保存在你的服务器上,那么只需将文本数据传递到你的服务器并使用某种服务器端语言执行文件编写代码。” 你能给任何链接教程吗?
2021-03-14 06:11:40
HTML5 API 最大仅 5 mb。
2021-04-09 06:11:40
是的,不选择它就不能写入系统文件。阅读官方文档:w3.org/TR/file-upload/#security-discussion
2021-04-09 06:11:40

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

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

尝试

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

如果您想下载二进制数据,请看这里

更新

2020.06.14 我将 Chrome 升级到 83.0 及更高版本 SO 代码段停止工作(原因:沙箱安全限制) - 但 JSFiddle 版本有效 -在这里

上面的答案很有用,但是,我发现代码可以帮助您在单击按钮时直接下载文本文件。在此代码中,您也可以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();
}
使用时需要小心createObjectURL与 JS 中的大多数事物不同,您使用它创建的对象不会在没有更多引用时自动垃圾收集;它们仅在页面关闭时被垃圾收集。由于您URL.revokeObjectURL()在此代码中没有使用释放上次调用使用的内存,因此存在内存泄漏;如果用户saveTextFile多次调用,他们将继续消耗越来越多的内存,因为您从未释放它。
2021-03-13 06:11:40
优秀。在 Opera 上为我工作。除了需要用语句“document.body.removeChild(event.target)”替换未知函数:“destroyClickedElement”
2021-03-28 06:11:40
您好,我不是 Web 开发人员,因此,首先感谢您的代码,它看起来很棒,但我不适合我。我尝试添加<form onsubmit="saveTextAsFile()">我的表单,并且更改了 downloadLink.download = "/home/myuser/myfile.txt",但它没有创建任何内容。有什么帮助吗?谢谢
2021-04-04 06:11:40