Ist es möglich, Daten nur mit JavaScript in eine Datei zu schreiben?

190

Ich möchte Daten mit JavaScript in eine vorhandene Datei schreiben. Ich möchte es nicht auf der Konsole drucken. Ich möchte tatsächlich Daten schreiben an abc.txt. Ich habe viele beantwortete Fragen gelesen, aber überall dort, wo sie auf der Konsole drucken. Irgendwann haben sie Code gegeben, aber er funktioniert nicht. Kann mir bitte jemand helfen, wie man tatsächlich Daten in eine Datei schreibt?

Ich habe den Code verwiesen, aber er funktioniert nicht: Es gibt einen Fehler:

Nicht erfasster TypeError: Unzulässiger Konstruktor

auf Chrom und

SecurityError: Der Vorgang ist unsicher.

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

Können wir also tatsächlich Daten nur mit Javascript oder NICHT in eine Datei schreiben?

Pareshm
quelle
2
Überprüfen Sie dieses heraus Bruder: stackoverflow.com/questions/585234/…
welbornio

Antworten:

89

Einige Vorschläge dazu -

  1. Wenn Sie versuchen, eine Datei auf dem Client-Computer zu schreiben, können Sie dies nicht browserübergreifend tun. IE verfügt über Methoden, mit denen "vertrauenswürdige" Anwendungen ActiveX-Objekte zum Lesen / Schreiben von Dateien verwenden können.
  2. Wenn Sie versuchen, es auf Ihrem Server zu speichern, geben Sie die Textdaten einfach an Ihren Server weiter und führen Sie den Dateischreibcode in einer serverseitigen Sprache aus.
  3. Um auf der Clientseite einige Informationen zu speichern, die sehr klein sind, können Sie Cookies verwenden.
  4. Verwenden der HTML5-API für den lokalen Speicher.
Sujit Agarwal
quelle
27
Die HTML5-API ist maximal 5 MB groß.
Pacerier
Ja, Sie können nicht in eine Systemdatei schreiben, ohne diese auszuwählen. Lesen Sie die offiziellen Dokumente
Manoj Ghediya
216

Sie können Dateien im Browser mit Blobund erstellen URL.createObjectURL. Alle neueren Browser unterstützen dies .

Sie können die von Ihnen erstellte Datei nicht direkt speichern, da dies zu massiven Sicherheitsproblemen führen würde. Sie können sie jedoch als Download-Link für den Benutzer bereitstellen. Sie können einen Dateinamen über das downloadAttribut des Links in Browsern vorschlagen , die das Download-Attribut unterstützen. Wie bei jedem anderen Download hat der Benutzer, der die Datei herunterlädt, das letzte Wort über den Dateinamen.

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

Hier ist ein Beispiel , das diese Technik verwendet, um beliebigen Text aus a zu speichern textarea.

Wenn Sie den Download sofort starten möchten, anstatt den Benutzer auf einen Link klicken zu müssen, können Sie Mausereignisse verwenden, um einen Mausklick auf den Link zu simulieren, wie es die Antwort von Lifecube getan hat. Ich habe ein aktualisiertes Beispiel erstellt , das diese Technik verwendet.

  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);
Nutzloser Code
quelle
1
@FirstBlood Welcher Teil funktioniert nicht, erhalten Sie eine Fehlermeldung? Die Datei- und Linkerstellung sollte in Safari 7+ funktionieren (ich glaube, dass Dinge auch in Safari 6 funktionieren sollten, wenn Sie die vorangestellte Version von verwenden URL). Das Festlegen des Dateinamens funktioniert in Safari nicht, da das downloadAttribut noch nicht implementiert wurde .
Nutzloser Code
1
Ich habe es auf Safari 5.1 versucht :)
First Blood
1
Das neue Zeilenzeichen fehlt im gespeicherten Dokument
Benny
1
@Benny die Zeilenumbruchzeichen sind da. JS verwendet das Zeilenumbruchzeichen \n, um neue Zeilen darzustellen, wie dies bei UNIX-Programmen der Fall ist . Sie sehen es wahrscheinlich in einem Windows-Programm wie Notepad, das das \nZeichen nicht als neue Zeile rendert . Wenn Sie möchten, dass die Zeilenumbrüche in Notepad und einigen anderen Windows-Programmen korrekt gerendert werden, Blobersetzen Sie sie \ndurch \r\n: text = text.replace(/\n/g, '\r\n').
Nutzloser Code
2
@ user3241111 Nicht wirklich, es sollte funktionieren. Solche Sachen sind gar nicht so ungewöhnlich. Ich habe Hackyer-Methoden gesehen ;-) In der Vergangenheit habe ich es auch geschafft, die Datei nur mouseoverüber den Link zu generieren , aber je nachdem, wie viel Verarbeitung sie macht, funktioniert das möglicherweise nicht besonders gut.
Nutzloser Code
41

Wenn Sie über Browser-Javascript sprechen, können Sie aus Sicherheitsgründen keine Daten direkt in die lokale Datei schreiben. Mit der neuen HTML 5-API können Sie nur Dateien lesen.

Wenn Sie jedoch Daten schreiben und dem Benutzer das Herunterladen als Datei in die lokale Datei ermöglichen möchten. Der folgende Code funktioniert:

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

um es zu benutzen:

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

Lebenswürfel
quelle
Erstaunlich, Lifecube. Ich brauchte diese Funktionalität wirklich, obwohl ich nicht möchte, dass der Benutzer weiß, dass eine Datei heruntergeladen wird, möchte ich, dass sie vollständig vor dem Benutzer verborgen ist, da sie den Benutzer möglicherweise ausflippen lässt, um zu sehen, dass eine Datei beim Ausführen einer Aktion automatisch heruntergeladen wird Können Sie auf einer Website, obwohl wir sie nur für Marketingdatenerfassungszwecke verwenden, mitteilen, wie die Datei heruntergeladen werden kann, ohne sie für den Benutzer sichtbar zu machen?
Just_another_developer
1
Die obige Lösung ist irgendwie veraltet. Möglicherweise müssen Sie die HTML 5-Javascript-Bibliothek berücksichtigen. github.com/eligrey/FileSaver.js
Lifecube
@Lifecube mit FileSaver.js, gibt es eine Möglichkeit, Text ohne Benutzerinteraktion automatisch in einer Datei zu speichern? Vielen Dank! Neu bei JS; Ihre ganze Hilfe wird geschätzt
Nathan
2
Zu mehreren Fragen zum Speichern einer Datei, ohne dass der Benutzer es weiß: Ein solches Verhalten wird durch das Design genau vermieden. Das würde die Büchse einer Pandora mit benutzerfreundlichen Sicherheitsbedrohungen öffnen. Cookies dienen zum Sammeln von Daten für Marketingzwecke.
Ari Okkonen
Hinweis Ich kann dies nicht dazu bringen, eine HTML-Datei als .html in Firefox v76 unter Windows 10 herunterzuladen. Am Ende des Downloads ist .pdf angehängt.
CSchwarz
23

Die obige Antwort ist nützlich, aber ich habe Code gefunden, mit dem Sie Textdateien direkt beim Klicken auf die Schaltfläche herunterladen können. In diesem Code können filenameSie auch nach Belieben ändern . Es ist eine reine Javascript-Funktion mit HTML5. Funktioniert bei mir!

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();
}
Niraj
quelle
2
Ausgezeichnet. Arbeitet für mich an der Oper. Außer die Notwendigkeit, die unbekannte Funktion zu ersetzen: "destroyClickedElement" durch die Anweisung "document.body.removeChild (event.target)"
steveOw
3
Sie müssen vorsichtig sein, wenn Sie verwenden createObjectURL. Im Gegensatz zu den meisten Dingen in JS werden die Objekte, die Sie damit erstellen, nicht automatisch durch Müll gesammelt, wenn keine Verweise mehr darauf vorhanden sind. Sie werden nur beim Schließen der Seite gesammelt. Da Sie URL.revokeObjectURL()diesen Code nicht verwenden, um den beim letzten Aufruf verwendeten Speicher freizugeben, liegt ein Speicherverlust vor. Wenn der Benutzer saveTextFilemehrmals anruft , belegt er weiterhin immer mehr Speicher, da Sie ihn nie freigegeben haben.
Nutzloser Code
19

Versuchen

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

Kamil Kiełczewski
quelle
6

Für den Fall, dass es nicht möglich ist, die neue BlobLösung zu verwenden, die mit Sicherheit die beste Lösung in einem modernen Browser ist, ist es immer noch möglich, diesen einfacheren Ansatz zu verwenden, der übrigens eine Begrenzung der Dateigröße aufweist:

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>

loretoparisi
quelle
3

Verwenden Sie den Code des Benutzers @ nutzloser-Code oben ( https://stackoverflow.com/a/21016088/327386 ), um die Datei zu generieren. Wenn Sie die Datei automatisch herunterladen möchten, übergeben Sie die textFilesoeben generierte an diese Funktion:

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;
}
U / min
quelle
5
Ich weiß nicht, warum dies eine negative Abstimmung bekam. Für mich geht das. Leute, die abstimmen, sollten zumindest einen Kommentar hinterlassen, warum dies abgelehnt wurde!
RPM
5
Ich habe nicht abgelehnt, aber es wird direkt davon abgeraten, Kommentare zur Abstimmung abzugeben. Der Benutzer sollte den Inhalt eines Beitrags kommentieren und über den Inhalt eines Beitrags abstimmen, seine Stimmen jedoch nicht kommentieren. Wenn jemand ohne Kommentar abstimmt, kann dies bedeuten, dass "diese Antwort nützlich ist" oder "diese Antwort ist nicht nützlich", je nach abgegebener Stimme.
Dies funktioniert nicht. Die Datei wird nicht heruntergeladen. Es wird nur ein Iframe erstellt, der ausgeblendet ist. Ich habe auf Chrome & Firefox getestet
NaiveCoder
2

Ich habe hier gute Antworten gefunden, aber auch einen einfacheren Weg gefunden.

Die Schaltfläche zum Erstellen des Blobs und des Download-Links kann in einem Link kombiniert werden, da das Link-Element ein Onclick-Attribut haben kann. (Das Gegenteil scheint nicht möglich zu sein. Das Hinzufügen eines href zu einer Schaltfläche funktioniert nicht.)

Sie können den Link als Schaltfläche mit gestalten bootstrap formatieren, bis auf das Styling immer noch reines Javascript verwenden.

Durch das Kombinieren der Schaltfläche und des Download-Links wird auch der Code reduziert, da weniger davon hässlich sind getElementById Aufrufe benötigt werden.

In diesem Beispiel ist nur ein Klick erforderlich, um den Text-Blob zu erstellen und herunterzuladen:

<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>
Roland
quelle
0

Ja es ist möglich Hier ist der Code

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

SM Turag
quelle