web-dev-qa-db-fra.com

JavaScript: créer et sauvegarder un fichier

J'ai des données que je veux écrire dans un fichier et ouvre une boîte de dialogue de fichier pour que l'utilisateur puisse choisir où sauvegarder le fichier. Ce serait formidable si cela fonctionnait dans tous les navigateurs, mais cela devait fonctionner dans Chrome. Je veux faire tout cela côté client.

En gros, je veux savoir quoi mettre dans cette fonction:

saveFile: function(data)
{
}

Lorsque la fonction récupère des données, l’utilisateur sélectionne un emplacement pour enregistrer le fichier et crée un fichier à cet emplacement avec ces données.

Utiliser HTML est bien aussi, si cela aide.

235
user1756980

Une amélioration très mineure du code de Awesomeness01 (pas besoin de balise d'ancrage) avec l'addition suggérée par trueimage (support de IE):

// Function to download data to a file
function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) // IE10+
        window.navigator.msSaveOrOpenBlob(file, filename);
    else { // Others
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}

Testé pour fonctionner correctement dans Chrome, FireFox et IE10.

Dans Safari, les données sont ouvertes dans un nouvel onglet et il faut enregistrer manuellement ce fichier.

203
Kanchu

Ce projet sur github semble prometteur:

https://github.com/eligrey/FileSaver.js

FileSaver.js implémente l'interface FileSaver de saveAs () du W3C dans les navigateurs qui ne la prennent pas en charge de manière native.

Regardez aussi la démo ici:

http://eligrey.com/demos/FileSaver.js/

124
lostsource
function download(text, name, type) {
  var a = document.getElementById("a");
  var file = new Blob([text], {type: type});
  a.href = URL.createObjectURL(file);
  a.download = name;
}
<a href="" id="a">click here to download your file</a>
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>

Et vous téléchargeriez ensuite le fichier en plaçant l'attribut download sur la balise d'ancrage.

La raison pour laquelle j'aime mieux cela que la création d'une URL de données est que vous n'avez pas à créer une URL longue et longue, vous pouvez simplement générer une URL temporaire.

114
Awesomeness01

Choisir l'emplacement où enregistrer le fichier avant de le créer n'est pas possible. Mais il est possible, du moins sous Chrome, de générer des fichiers en utilisant uniquement JavaScript. Voici un ancien exemple de création de fichier CSV. L'utilisateur sera invité à le télécharger. Malheureusement, cela ne fonctionne pas bien dans les autres navigateurs, notamment IE.

<!DOCTYPE html>
<html>
<head>
    <title>JS CSV</title>
</head>
<body>
    <button id="b">export to CSV</button>
    <script type="text/javascript">
        function exportToCsv() {
            var myCsv = "Col1,Col2,Col3\nval1,val2,val3";

            window.open('data:text/csv;charset=utf-8,' + escape(myCsv));
        }

        var button = document.getElementById('b');
        button.addEventListener('click', exportToCsv);
    </script>
</body>
</html>
37
Matt Greer
setTimeout("create('Hello world!', 'myfile.txt', 'text/plain')");
function create(text, name, type) {
  var dlbtn = document.getElementById("dlbtn");
  var file = new Blob([text], {type: type});
  dlbtn.href = URL.createObjectURL(file);
  dlbtn.download = name;
}
<a href="javascript:void(0)" id="dlbtn"><button>click here to download your file</button></a>
18
Samuel Tees

Pour le dernier navigateur, comme Chrome, vous pouvez utiliser le API de fichier comme dans ce tutoriel :

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, saveFile, errorHandler);
13
pdjota

Essayez d’utiliser ceci pour télécharger le fichier et tout ce que vous avez à faire est de modifier les attributs onclick.

function download(text, name, type) {
  var a = document.getElementById("a");
  a.style.display = "block";
  var file = new Blob([text], {type: type});
  a.href = URL.createObjectURL(file);
  a.download = name;
}
#a { display: none; }
<a href="" id="a" download>click here to download your file</a>
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>
12
boomcreeper11

J'ai essayé cela dans la console et ça marche.

var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob
window.open(URL.createObjectURL(oMyBlob));
8
Netsi1964

Vous ne pouvez pas le faire uniquement en Javascript. Javascript pour les navigateurs n'a pas encore la permission (il y a eu des propositions) pour des raisons de sécurité.

Au lieu de cela, je recommanderais d'utiliser Downloadify :

Une minuscule bibliothèque javascript + Flash qui permet la création et le téléchargement de fichiers texte sans interaction du serveur.

Vous pouvez voir une simple démonstration ici où vous fournissez le contenu et pouvez tester la fonctionnalité de sauvegarde/annulation/traitement des erreurs.

5
Aamir

Pour Chrome et Firefox, j'utilise une méthode purement JavaScript.

(Mon application ne peut pas utiliser un package tel que Blob.js parce qu'il est servi à partir d'un moteur spécial: un DSP avec un serveur WWWeb saturé et peu de place pour quoi que ce soit.)

function FileSave(sourceText, fileIdentity) {
    var workElement = document.createElement("a");
    if ('download' in workElement) {
        workElement.href = "data:" + 'text/plain' + "charset=utf-8," + escape(sourceText);
        workElement.setAttribute("download", fileIdentity);
        document.body.appendChild(workElement);
        var eventMouse = document.createEvent("MouseEvents");
        eventMouse.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        workElement.dispatchEvent(eventMouse);
        document.body.removeChild(workElement);
    } else throw 'File saving not supported for this browser';
}

Notes, mises en garde et mots de belette:

  • Ce code a été utilisé avec succès dans les clients Chrome et Firefox exécutés dans les environnements Linux (Maipo) et Windows (7 et 10).
  • Toutefois, si sourceText est supérieur à un Mo, Chrome est parfois bloqué dans son propre téléchargement sans indication d'échec; Firefox, jusqu'à présent, n'a pas présenté ce comportement. La cause pourrait être une limitation de blob dans Chrome. Franchement, je ne sais tout simplement pas; si quelqu'un a des idées sur la façon de corriger (ou au moins de détecter), veuillez poster. Si l'anomalie de téléchargement se produit, lorsque le navigateur Chrome est fermé, il génère un diagnostic tel que Chrome browser diagnostic
  • Ce code n'est pas compatible avec Edge ou Internet Explorer. Je n'ai pas essayé Opera ni Safari.
2
We B Martians

Javascript possède une API FileSystem. Si vous ne pouvez pas utiliser cette fonctionnalité uniquement dans Chrome, voici un bon point de départ: http://www.html5rocks.com/fr/tutorials/file/filesystem/ .

1
Alok

StreamSaver est une alternative pour enregistrer des fichiers très volumineux sans avoir à conserver toutes les données en mémoire.
En fait, il émule tout ce que le serveur dose lors de l’enregistrement d’un fichier, mais tout côté client avec le service worker.

Vous pouvez obtenir le rédacteur et y écrire manuellement celui de Uint8Array ou diriger un flux readableStream binaire vers le flux accessible en écriture

Il y a quelques exemple mettant en vedette:

  • Comment enregistrer plusieurs fichiers au format Zip
  • acheminant un flux lisible, par exemple de Response ou blob.stream() à StreamSaver
  • écrire manuellement dans le flux en écriture à mesure que vous tapez quelque chose
  • ou recodage d'une vidéo/audio

Voici un exemple sous sa forme la plus simple:

const fileStream = streamSaver.createWriteStream('filename.txt')

new Response('StreamSaver is awesome').body
  .pipeTo(fileStream)
  .then(success, error)

Si vous souhaitez enregistrer un blob, vous devez simplement le convertir en un flux lisible.

new Response(blob).body.pipeTo(...) // response hack
blob.stream().pipeTo(...) // feature reference
0
Endless