Est-il possible d'écrire des données dans un fichier en utilisant uniquement JavaScript?

192

Je souhaite écrire des données dans un fichier existant à l'aide de JavaScript. Je ne veux pas l'imprimer sur la console. Je veux réellement écrire des données dans abc.txt. J'ai lu de nombreuses questions répondues, mais partout où elles sont imprimées sur console. à un endroit, ils ont donné du code mais ça ne fonctionne pas. Alors, s'il vous plaît, quelqu'un peut-il m'aider Comment écrire des données dans un fichier.

J'ai fait référence au code mais ça ne fonctionne pas: ça donne une erreur:

Uncaught TypeError: constructeur illégal

sur chrome et

SecurityError: l'opération n'est pas sécurisée.

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

Alors pouvons-nous réellement écrire des données dans un fichier en utilisant uniquement Javascript ou PAS?

pareshm
la source

Réponses:

90

Quelques suggestions pour cela -

  1. Si vous essayez d'écrire un fichier sur la machine cliente, vous ne pouvez pas le faire de manière cross-browser. IE a des méthodes pour permettre aux applications «de confiance» d'utiliser des objets ActiveX pour lire / écrire un fichier.
  2. Si vous essayez de l'enregistrer sur votre serveur, transmettez simplement les données texte à votre serveur et exécutez le code d'écriture du fichier en utilisant un langage côté serveur.
  3. Pour stocker certaines informations côté client qui sont considérablement petites, vous pouvez opter pour les cookies.
  4. Utilisation de l'API HTML5 pour le stockage local.
Sujit Agarwal
la source
27
L'API HTML5 est limitée à 5 Mo uniquement.
Pacerier
Oui, vous ne pouvez pas écrire dans le fichier système sans le sélectionner. Lire la documentation officielle: w3.org/TR/file-upload/#security-discussion
Manoj Ghediya
217

Vous pouvez créer des fichiers dans le navigateur en utilisant Blobet URL.createObjectURL. Tous les navigateurs récents le prennent en charge .

Vous ne pouvez pas enregistrer directement le fichier que vous créez, car cela poserait d'énormes problèmes de sécurité, mais vous pouvez le fournir en tant que lien de téléchargement pour l'utilisateur. Vous pouvez proposer un nom de fichier via l' downloadattribut du lien, dans les navigateurs prenant en charge l'attribut de téléchargement. Comme pour tout autre téléchargement, l'utilisateur qui télécharge le fichier aura le dernier mot sur le nom du fichier.

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

Voici un exemple qui utilise cette technique pour enregistrer du texte arbitraire à partir d'un fichier textarea.

Si vous souhaitez lancer immédiatement le téléchargement au lieu de demander à l'utilisateur de cliquer sur un lien, vous pouvez utiliser des événements de souris pour simuler un clic de souris sur le lien comme l'a fait la réponse de Lifecube . J'ai créé un exemple mis à jour qui utilise cette technique.

  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);
Code inutile
la source
1
@FirstBlood Quelle partie ne fonctionne pas, obtenez-vous une erreur? La création de fichiers et de liens devrait fonctionner dans Safari 7+ (je pense que cela devrait également fonctionner dans Safari 6 si vous utilisez la version préfixée de URL). La définition du nom de fichier ne fonctionnera pas dans Safari car il n'a toujours pas implémenté l' downloadattribut .
Code inutile
1
J'essayais sur Safari 5.1 :)
First Blood
1
le caractère de nouvelle ligne est absent du document enregistré
Benny
1
@Benny les caractères de nouvelle ligne sont là. JS utilise le caractère de nouvelle ligne \npour représenter les nouvelles lignes comme le font les programmes UNIX. Vous l'affichez probablement dans un programme Windows, tel que le Bloc-notes, qui ne rend pas le \ncaractère comme une nouvelle ligne . Si vous voulez que les nouvelles lignes à rendre correctement dans le Bloc - notes et d'autres programmes Windows, avant de mettre le texte dans le Blobremplacer chaque \navec \r\n: text = text.replace(/\n/g, '\r\n').
Code inutile
2
@ user3241111 Pas vraiment, ça devrait marcher. Des trucs comme ça ne sont pas si inhabituels. J'ai vu des moyens de piratage pour le faire ;-) Dans le passé, je me suis aussi contenté de générer le fichier sur mouseoverle lien, mais en fonction de la quantité de traitement qu'il effectue, cela pourrait ne pas fonctionner très bien.
Code inutile
41

Si vous parlez de javascript de navigateur, vous ne pouvez pas écrire de données directement dans un fichier local pour des raisons de sécurité. La nouvelle API HTML 5 peut uniquement vous permettre de lire des fichiers.

Mais si vous souhaitez écrire des données et permettre à l'utilisateur de télécharger en tant que fichier local. le code suivant fonctionne:

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

pour l'utiliser:

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

Lifecube
la source
Incroyable, Lifecube. J'avais vraiment besoin de cette fonctionnalité, même si je ne veux pas que l'utilisateur sache qu'un fichier est en cours de téléchargement, je veux qu'il soit complètement caché à l'utilisateur car cela pourrait effrayer l'utilisateur de voir qu'un fichier est téléchargé automatiquement après une action sur un site Web, bien que nous l'utilisions uniquement à des fins de collecte de données marketing, pourriez-vous s'il vous plaît partager comment télécharger le fichier sans le rendre visible à l'utilisateur?
Just_another_developer
1
la solution ci-dessus est un peu dépassée. Vous devrez peut-être considérer la bibliothèque javascript html 5. github.com/eligrey/FileSaver.js
Lifecube
@Lifecube en utilisant FileSaver.js, existe-t-il un moyen d'enregistrer automatiquement du texte dans un fichier sans intervention de l'utilisateur? Merci! Nouveau sur JS; toute votre aide est appréciée
Nathan
3
À plusieurs questions sur l'enregistrement d'un fichier sans que l'utilisateur le sache: Un tel comportement est justement ce qui est évité par la conception. Cela ouvrirait la boîte de Pandore de menaces de sécurité faciles à utiliser. Les cookies servent à collecter des données à des fins de marketing.
Ari Okkonen
Remarque Je ne peux pas obtenir cela pour télécharger un fichier html en tant que .html dans Firefox v76 sur Windows 10. Le téléchargement a .pdf ajouté à la fin.
CSchwarz
23

La réponse ci-dessus est utile, mais j'ai trouvé un code qui vous aide à télécharger un fichier texte directement en cliquant sur le bouton. Dans ce code, vous pouvez également changer filenamecomme vous le souhaitez. C'est une fonction javascript pure avec HTML5. Travaille pour moi!

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
la source
2
Excellent. Fonctionne pour moi sur Opera. Sauf nécessité de remplacer la fonction inconnue: "destroyClickedElement" par l'instruction "document.body.removeChild (event.target)"
steveOw
3
Vous devez être prudent lors de l'utilisation createObjectURL. Contrairement à la plupart des choses dans JS, les objets que vous créez avec lui ne sont pas automatiquement récupérés lorsqu'il n'y a plus de références à eux; ils ne sont récupérés que lorsque la page se ferme. Puisque vous n'utilisez pas URL.revokeObjectURL()dans ce code pour libérer la mémoire utilisée par le dernier appel, vous avez une fuite de mémoire; si l'utilisateur appelle saveTextFileplusieurs fois, il continuera à consommer de plus en plus de mémoire car vous ne l'avez jamais libérée.
Code inutile
20

Essayer

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

Kamil Kiełczewski
la source
6

Dans le cas où il n'est pas possible d'utiliser la nouvelle Blobsolution, qui est certainement la meilleure solution dans un navigateur moderne, il est toujours possible d'utiliser cette approche plus simple, qui a une limite dans la taille du fichier en passant:

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
la source
3

Utilisez le code de l'utilisateur @ useless-code ci-dessus ( https://stackoverflow.com/a/21016088/327386 ) pour générer le fichier. Si vous souhaitez télécharger le fichier automatiquement, passez le textFilequi vient d'être généré à cette fonction:

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;
}
RPM
la source
5
Je ne sais pas pourquoi cela a obtenu un vote négatif. Ça marche pour moi. Les gens qui votent contre devraient au moins laisser un commentaire expliquant pourquoi cela a été voté contre!
RPM
5
Je n'ai pas voté contre, mais en fait, commenter le vote est directement déconseillé. L'utilisateur doit commenter le contenu d'un message et voter sur le contenu d'un message, mais il ne doit pas commenter son vote. Si quelqu'un vote sans faire de commentaire, vous pouvez considérer que cela signifie «cette réponse est utile» ou «cette réponse n'est pas utile» selon le vote exprimé.
Cela ne fonctionne pas. Il ne télécharge pas le fichier. Cela crée simplement une iframe qui est cachée. J'ai testé sur chrome et firefox
NaiveCoder
2

J'ai trouvé de bonnes réponses ici, mais j'ai également trouvé un moyen plus simple.

Le bouton pour créer l'objet blob et le lien de téléchargement peuvent être combinés en un seul lien, car l'élément link peut avoir un attribut onclick. (L'inverse ne semble pas possible, l'ajout d'un href à un bouton ne fonctionne pas.)

Vous pouvez bootstrapstyliser le lien comme un bouton en utilisant , qui est toujours du javascript pur, sauf pour le style.

La combinaison du bouton et du lien de téléchargement réduit également le code, car moins de ces getElementByIdappels laids sont nécessaires.

Cet exemple ne nécessite qu'un seul clic pour créer le blob de texte et le télécharger:

<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
la source
0

Oui c'est possible Ici le code est

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
la source