È possibile scrivere dati su file usando solo JavaScript?


192

Voglio scrivere dati su file esistenti usando JavaScript. Non voglio stamparlo su console. Voglio effettivamente scrivere i dati in abc.txt. Ho letto molte domande con risposta ma ogni dove sono in stampa su console. in qualche posto hanno dato il codice ma non funziona. Quindi, per favore, qualcuno può aiutarmi Come scrivere effettivamente i dati su File.

Ho fatto riferimento al codice ma non funziona: sta dando errore:

Uncaught TypeError: costruttore illegale

su cromo e

SecurityError: l'operazione non è sicura.

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

Quindi possiamo effettivamente scrivere dati su file usando solo Javascript o NOT?



Risposte:


90

Alcuni suggerimenti per questo -

  1. Se si sta tentando di scrivere un file sul computer client, non è possibile farlo in alcun modo tra browser. IE ha metodi per abilitare le applicazioni "attendibili" a utilizzare oggetti ActiveX per leggere / scrivere file.
  2. Se stai cercando di salvarlo sul tuo server, passa semplicemente i dati di testo al tuo server ed esegui il codice di scrittura del file usando una lingua lato server.
  3. Per memorizzare alcune informazioni sul lato client che sono considerevolmente piccole, puoi scegliere i cookie.
  4. Utilizzo dell'API HTML5 per l'archiviazione locale.

27
L'API HTML5 ha un limite massimo di 5 mb.
Pacerier,

Sì, non è possibile scrivere nel file di sistema senza selezionarlo. Leggi documenti ufficiali: w3.org/TR/file-upload/#security-discussion
Manoj Ghediya

217

È possibile creare file nel browser utilizzando Blobe URL.createObjectURL. Tutti i browser recenti supportano questo .

Non è possibile salvare direttamente il file creato, poiché ciò causerebbe enormi problemi di sicurezza, ma è possibile fornirlo come collegamento per il download per l'utente. Puoi suggerire un nome file tramite l' downloadattributo del link, nei browser che supportano l'attributo download. Come con qualsiasi altro download, l'utente che scarica il file avrà comunque l'ultima parola sul nome del file.

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

Ecco un esempio che utilizza questa tecnica per salvare testo arbitrario da a textarea.

Se si desidera avviare immediatamente il download anziché richiedere all'utente di fare clic su un collegamento, è possibile utilizzare gli eventi del mouse per simulare un clic del mouse sul collegamento come ha fatto la risposta di Lifecube . Ho creato un esempio aggiornato che utilizza questa tecnica.

  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 Quale parte non funziona, ricevi un errore? La creazione di file e collegamenti dovrebbe funzionare in Safari 7+ (credo che le cose dovrebbero funzionare anche in Safari 6 se usi la versione con prefisso di URL). L'impostazione del nome del file non funzionerà in Safari perché non ha ancora implementato l' downloadattributo .
Codice inutile

1
Lo stavo provando su Safari 5.1 :)
First Blood

1
il nuovo personaggio della linea non è presente nel documento salvato
Benny,

1
@Benny i personaggi newline ci sono. JS usa il carattere newline \nper rappresentare nuove linee come fanno i programmi UNIX. Probabilmente lo stai visualizzando in un programma Windows, come Blocco note, che non rende il \npersonaggio come una nuova riga . Se si desidera che i ritorni a capo per essere resi correttamente in Blocco note e alcuni altri programmi di Windows, prima di mettere il testo nel Blobsostituire ogni \ncon \r\n: text = text.replace(/\n/g, '\r\n').
Codice inutile

2
@ user3241111 Non proprio, dovrebbe funzionare. Roba del genere non è poi così insolita. Ho visto modi più disordinati di farlo ;-) In passato ho anche evitato di generare il file sul mouseoverlink, ma a seconda di quanta elaborazione stia facendo potrebbe non funzionare alla grande.
Codice inutile

41

Se stai parlando del javascript del browser, non puoi scrivere i dati direttamente nel file locale per motivi di sicurezza. La nuova API HTML 5 ti consente solo di leggere i file.

Ma se si desidera scrivere dati e consentire all'utente di scaricare come file in locale. funziona il seguente codice:

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

per usarlo:

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


Fantastico, Lifecube. Avevo davvero bisogno di quella funzionalità, anche se non voglio che l'utente sappia che qualsiasi file è in fase di download, lo voglio completamente nascosto all'utente in quanto potrebbe spaventare l'utente nel vedere che alcuni file vengono scaricati automaticamente dopo aver fatto qualche azione su un sito Web, sebbene lo stiamo utilizzando solo a scopo di raccolta di dati di marketing, potresti condividere come scaricare il file senza renderlo visibile all'utente?
Just_another_developer,

1
la soluzione sopra è in qualche modo obsoleta. Potrebbe essere necessario prendere in considerazione la libreria html 5 javascript. github.com/eligrey/FileSaver.js
Lifecube il

@Lifecube utilizzando FileSaver.js, c'è un modo per salvare automaticamente il testo in un file senza l'interazione dell'utente? Grazie! Nuovo in JS; tutto il tuo aiuto è apprezzato
Nathan,

3
A diverse domande sul salvataggio di un file senza che l'utente lo sappia: tale comportamento è proprio ciò che viene evitato dal progetto. Ciò aprirebbe una scatola di Pandora di minacce alla sicurezza facili da usare. I cookie servono per raccogliere dati a fini di marketing.
Ari Okkonen,

Nota Non riesco a ottenere questo per scaricare un file html come .html in firefox v76 su Windows 10. Il download ha .pdf aggiunto alla fine di esso.
CSchwarz,

23

La risposta sopra è utile, ma ho trovato il codice che ti aiuta a scaricare il file di testo direttamente sul pulsante. In questo codice puoi anche cambiare filenamecome desideri. È pura funzione JavaScript con HTML5. Per me va bene!

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
Eccellente. Funziona per me su Opera. Tranne la necessità di sostituire la funzione sconosciuta: "destroyClickedElement" dall'istruzione "document.body.removeChild (event.target)"
steveOw

3
Devi stare attento quando lo usi createObjectURL. Diversamente dalla maggior parte delle cose in JS, gli oggetti che crei con essa non vengono automaticamente raccolti in modo inutile quando non ci sono più riferimenti ad essi; sono solo spazzatura raccolti alla chiusura della pagina. Poiché non si utilizza URL.revokeObjectURL()questo codice per liberare la memoria utilizzata dall'ultima chiamata, si verifica una perdita di memoria; se l'utente chiama saveTextFilepiù volte, continuerà a consumare sempre più memoria perché non l'hai mai rilasciato.
Codice inutile

20

Provare

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


6

Nel caso in cui non sia possibile utilizzare la nuova Blobsoluzione, che è sicuramente la migliore soluzione nel browser moderno, è ancora possibile utilizzare questo approccio più semplice, che ha un limite nella dimensione del file tra l'altro:

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

Utilizzare il codice dell'utente @ codice inutile sopra ( https://stackoverflow.com/a/21016088/327386 ) per generare il file. Se si desidera scaricare automaticamente il file, passare textFileciò che è stato appena generato a questa funzione:

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
Non so perché questo abbia un voto negativo. Per me funziona. Le persone che votano verso il basso dovrebbero almeno lasciare un commento sul perché questo è stato votato verso il basso!
RPM

5
Non ho votato a fondo, ma in realtà commentare il voto è direttamente scoraggiato. L'utente dovrebbe commentare il contenuto di un post e votare il contenuto di un post, ma non dovrebbe commentare i propri voti. Se qualcuno vota senza commentare, puoi intenderlo "questa risposta è utile" o "questa risposta non è utile" a seconda del voto espresso.

Questo non funziona .. Non scarica il file. Crea solo un iframe che è nascosto. Ho provato su Chrome e Firefox
NaiveCoder il

2

Ho trovato buone risposte qui, ma ho anche trovato un modo più semplice.

Il pulsante per creare il BLOB e il collegamento per il download può essere combinato in un collegamento, poiché l'elemento del collegamento può avere un attributo onclick. (Il contrario non sembra possibile, l'aggiunta di un href a un pulsante non funziona.)

Puoi bootstrapmodellare il link come un pulsante usando , che è ancora javascript puro, tranne che per lo stile.

La combinazione del pulsante e del collegamento per il download riduce anche il codice, poiché getElementByIdsono necessarie meno di quelle brutte chiamate.

Questo esempio richiede solo un clic del pulsante per creare il BLOB di testo e scaricarlo:

<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

Sì, è possibile Qui il codice è

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.