Verwenden von HTML5 / JavaScript zum Generieren und Speichern einer Datei

317

Ich habe in letzter Zeit mit WebGL herumgespielt und einen Collada-Leser zum Laufen gebracht. Das Problem ist, dass es ziemlich langsam ist (Collada ist ein sehr ausführliches Format), daher werde ich anfangen, Dateien in ein einfacher zu verwendendes Format (wahrscheinlich JSON) zu konvertieren. Ich habe bereits den Code zum Parsen der Datei in JavaScript, daher kann ich ihn auch als Exporteur verwenden! Das Problem ist das Speichern.

Jetzt weiß ich, dass ich die Datei analysieren, das Ergebnis an den Server senden und vom Browser die Datei als Download vom Server zurückfordern lassen kann. In Wirklichkeit hat der Server jedoch nichts mit diesem bestimmten Prozess zu tun. Warum sollte er also beteiligt werden? Ich habe bereits den Inhalt der gewünschten Datei im Speicher. Gibt es eine Möglichkeit, dem Benutzer einen Download mit reinem JavaScript zu präsentieren? (Ich bezweifle es, könnte aber genauso gut fragen ...)

Und um klar zu sein: Ich versuche nicht, ohne Wissen des Benutzers auf das Dateisystem zuzugreifen! Der Benutzer stellt eine Datei bereit (wahrscheinlich per Drag & Drop), das Skript transformiert die Datei im Speicher und der Benutzer wird aufgefordert, das Ergebnis herunterzuladen. All dies sollten für den Browser "sichere" Aktivitäten sein.

[BEARBEITEN]: Ich habe es nicht im Voraus erwähnt, daher sind die Poster, die mit "Flash" geantwortet haben, gültig genug, aber ein Teil meiner Arbeit besteht darin, hervorzuheben, was mit reinem HTML5 möglich ist ... also ist Flash direkt in meinem Fall. (Obwohl dies eine absolut gültige Antwort für jeden ist, der eine "echte" Web-App erstellt.) In diesem Fall habe ich anscheinend kein Glück, es sei denn, ich möchte den Server einbeziehen. Danke trotzdem!

Toji
quelle
8
Sie könnten erwägen, die akzeptierte Antwort zu ändern, es scheint jetzt einen rein HTML-Weg zu geben
Pekka

Antworten:

256

OK, Daten erstellen: URI macht definitiv den Trick für mich, dank Matthew und Dennkster, die auf diese Option hinweisen! Hier ist im Grunde, wie ich es mache:

1) Holen Sie sich den gesamten Inhalt in eine Zeichenfolge namens "Inhalt" (z. B. indem Sie ihn zunächst dort erstellen oder innerHTML des Tags einer bereits erstellten Seite lesen).

2) Erstellen Sie den Daten-URI:

uriContent = "data:application/octet-stream," + encodeURIComponent(content);

Abhängig vom Browsertyp usw. gibt es Längenbeschränkungen, aber z. B. funktioniert Firefox 3.6.12 bis mindestens 256 KB. Das Codieren in Base64 anstelle von encodeURIComponent könnte die Dinge effizienter machen, aber für mich war das in Ordnung.

3) Öffnen Sie ein neues Fenster und leiten Sie es zu diesem URI um. Sie werden aufgefordert, einen Download-Speicherort für meine von JavaScript generierte Seite einzugeben:

newWindow = window.open(uriContent, 'neuesDokument');

Das ist es.

Nøk
quelle
34
Wenn Sie die Verwendung eines Popups vermeiden möchten, das blockiert werden kann, können Sie das location.hrefauf den Inhalt einstellen . location.href = uriContent.
Alex Turpin
12
Hallo, ich habe es versucht, aber es lädt die Datei als .part-Datei herunter. Wie kann ich den Dateityp einstellen?
Sedat Başar
6
@ SedatBaşar Daten-URIs unterstützen das Festlegen eines Dateinamens nicht. Sie müssen sich darauf verlassen, dass der Browser mithilfe des MIME-Typs eine geeignete Erweiterung festlegt. Wenn der MIME-Typ jedoch vom Browser gerendert werden kann, wird er nicht heruntergeladen, sondern angezeigt. Es gibt einige andere Möglichkeiten, dies zu tun, aber beide funktionieren nicht in IE <10.
Panzi
7
IE unterstützt Daten-URIs nicht wirklich und Firefox scheint die Dateien unter einem zufälligen Namen zu speichern.
Nylund
25
Ich denke, wir machen das schwieriger als nötig. Öffnen Sie Ihre JS-Konsole auf dieser Seite und platzieren Sie location.href = "data:application/octet-stream," + encodeURIComponent(jQuery('#answer-4551467 .post-text').first().text());sie. Der Inhalt von @ Nøks Antwort wird in einer Datei gespeichert. Ich habe keinen IE, um es zu testen, aber es funktioniert für Webkit.
Bruno Bronosky
278

Einfache Lösung für HTML5-fähige Browser ...

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    }
    else {
        pom.click();
    }
}

Verwendungszweck

download('test.txt', 'Hello world!');
Matěj Pokorný
quelle
2
Wenn Sie die Quell-URL kennen, die Sie herunterladen möchten, ist dies die beste Lösung!
Sidonaldson
31
Die Möglichkeit, den Dateinamen festzulegen, macht dies zu einem Gewinner.
Omn
9
Diese Methode funktionierte in Chrome bis zum letzten Update, das ich vor einigen Tagen erhalten habe (35.0.1916.114 m). Jetzt funktioniert es teilweise dadurch, dass der Dateiname und die Erweiterung nicht mehr funktionieren (es benennt immer die Datei download.txt, unabhängig davon, was übergeben wird.)
Sevin7
6
Ich habe Chrom 42.0.2311.90 und dies funktioniert für mich mit dem erwarteten Dateinamen.
Saurabh Kumar
4
Gibt es eine Begrenzung für die Datenmenge, die aufgenommen werden kann?
Kaspar Lee
80

HTML5 hat eine window.saveAs(blob, filename)Methode definiert . Es wird derzeit von keinem Browser unterstützt. Es gibt jedoch eine Kompatibilitätsbibliothek namens FileSaver.js , die diese Funktion den meisten modernen Browsern (einschließlich Internet Explorer 10+) hinzufügt. Internet Explorer 10 unterstützt eine navigator.msSaveBlob(blob, filename)Methode ( MSDN ), die in FileSaver.js für die Unterstützung von Internet Explorer verwendet wird.

Ich habe einen Blogeintrag mit weiteren Details zu diesem Problem geschrieben.

Panzi
quelle
1
Was ist mit dem Blockieren von Popups? Das Verhalten dieser Bibliothek ähnelt der von @ Nøk. Nur-Text in Firefox wird in einem neuen geöffnet. Nur Chrome versucht, es zu speichern, aber es ändert die Erweiterung (ich benötige eine Punktdatei ohne Erweiterung).
Ciembor
1
@ciembor Mit der Download-Attributvariante (Objekt-URL +) (die ich mit Chrome verwende) können Sie einen Dateinamen festlegen. Es funktioniert bei mir in Chrom.
Panzi
1
@ciembor aha und ein Popup wird nicht blockiert, wenn ein Klick es direkt verursacht hat.
Panzi
6
FileSaver.js unterstützt jetzt IE
Eli Gray
15
W3C sagt: Die Arbeit an diesem Dokument wurde eingestellt und sollte nicht referenziert oder als Grundlage für die Implementierung verwendet werden.
WaiKit Kung
48

Große Dateien speichern

Lange Daten-URIs können in Browsern zu Leistungsproblemen führen. Eine weitere Option zum Speichern clientseitig generierter Dateien besteht darin, deren Inhalt in ein Blob- (oder Datei-) Objekt einzufügen und mithilfe einen Download-Link zu erstellen URL.createObjectURL(blob). Dies gibt eine URL zurück, mit der der Inhalt des Blobs abgerufen werden kann. Der Blob wird im Browser gespeichert, bis entweder URL.revokeObjectURL()die URL aufgerufen wird oder das Dokument, das ihn erstellt hat, geschlossen wird. Die meisten Webbrowser unterstützen Objekt-URLs . Opera Mini ist der einzige, der sie nicht unterstützt.

Download erzwingen

Wenn es sich bei den Daten um Text oder ein Bild handelt, kann der Browser die Datei öffnen, anstatt sie auf der Festplatte zu speichern. Um zu bewirken, dass die Datei beim Klicken auf den Link heruntergeladen wird, können Sie das downloadAttribut verwenden. Allerdings unterstützen nicht alle Webbrowser das Download-Attribut . Eine andere Option ist die Verwendung application/octet-streamals MIME-Typ der Datei. Dies führt jedoch dazu, dass die Datei als binärer Blob dargestellt wird. Dies ist besonders benutzerunfreundlich, wenn Sie keinen Dateinamen angeben oder nicht angeben können. Siehe auch Popup ' Öffnen unter "Speichern unter ...", das beim Klicken auf einen Textlink geöffnet wird. Klicken Sie für PDF in HTML. '

Angeben eines Dateinamens

Wenn der Blob mit dem Dateikonstruktor erstellt wird, können Sie auch einen Dateinamen festlegen, aber nur wenige Webbrowser (einschließlich Chrome und Firefox) unterstützen den Dateikonstruktor . Der Dateiname kann auch als Argument für das downloadAttribut angegeben werden, dies unterliegt jedoch einer Reihe von Sicherheitsaspekten . Internet Explorer 10 und 11 bieten eine eigene Methode, msSaveBlob , um einen Dateinamen anzugeben.

Beispielcode

var file;
var data = [];
data.push("This is a test\n");
data.push("Of creating a file\n");
data.push("In a browser\n");
var properties = {type: 'text/plain'}; // Specify the file's mime-type.
try {
  // Specify the filename using the File constructor, but ...
  file = new File(data, "file.txt", properties);
} catch (e) {
  // ... fall back to the Blob constructor if that isn't supported.
  file = new Blob(data, properties);
}
var url = URL.createObjectURL(file);
document.getElementById('link').href = url;
<a id="link" target="_blank" download="file.txt">Download</a>

bcmpinc
quelle
1
Kann ich ein Dialogfeld (Popup) anzeigen, um einen Ordner (Verzeichnis) zum Speichern der Datei anzugeben?
Calvin
@Calvin: Ich habe die Antwort aktualisiert, um zu erklären, wie ein Download erzwungen und ein Dateiname angegeben wird. Ich glaube, Sie können für IE msSaveBlobdas Dialogfeld "Speichern unter" öffnen. Bei anderen Browsern können Sie nur manuell "Speichern unter" aus dem Kontextmenü des Download-Links auswählen.
bcmpinc
1
@ Jek-fdrv: In Safari funktionieren nur die Blob-URLs. Das Download-Attribut und der Dateikonstruktor werden von Safari nicht unterstützt, sodass Sie keinen Download erzwingen können. Dies bedeutet, dass der Blob wahrscheinlich im Browser selbst geöffnet wird und Sie keinen Dateinamen angeben können. Für das angegebene Beispiel sollten Sie weiterhin in der Lage sein, die Datei mit Safari über das Kontextmenü des Links herunterzuladen.
bcmpinc
Dies ist eine sehr hilfreiche und informative Antwort. Eine weitere Sache, die Leuten wie mir helfen kann: Nach dem Festlegen document.getElementById('link').href = url;kann Ihr Code den Link mithilfe der .click()Methode des Elements auslösen.
LarsH
36
function download(content, filename, contentType)
{
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}
Yassir Ennazk
quelle
3
Was bewirkt der contentType? Was wird es verwendet?
Uri
3
Dieser funktioniert auch im neuesten Chrome einwandfrei, im Gegensatz zu der Antwort von @ Matěj Pokorný. Vielen Dank.
Alexander Amelkin
2
Dies funktioniert bei FF36 oder IE11 nicht. Wenn ich durch a.clickCode ersetze , document.createEvent()wie von Matěj Pokorný vorgeschlagen, funktioniert dies auf FF, aber nicht auf IE. Ich habe Chrome nicht ausprobiert.
Peter Hull
25

Schauen Sie sich dazu Doug Neiners Downloadify an , eine Flash-basierte JavaScript-Oberfläche.

Downloadify ist eine winzige JavaScript + Flash-Bibliothek, die das Generieren und Speichern von Dateien im laufenden Betrieb im Browser ohne Serverinteraktion ermöglicht.

Pekka
quelle
6
Für die meisten Menschen ist dies wahrscheinlich die Antwort, die sie brauchen werden. Obwohl es nicht meinen spezifischen Anforderungen entspricht (wie oben erläutert), markiere ich es als akzeptierte Antwort.
Toji
2
@ Toji ah, ich verstehe. Vielleicht unter dem HTML 5Banner erneut fragen und umformulieren und entsprechend markieren? Das würde wahrscheinlich diejenigen Benutzer anziehen, die sich mit diesem speziellen Bereich auskennen (ich nehme an, es ist derzeit noch eine vergleichsweise kleine Menge). Ich bin mir ziemlich sicher, dass dies in HTML 5 möglich ist, aber ich habe keine Ahnung, wie.
Pekka
1
Wurde die Downloadify.info Downloadify-Domain gekauft / übertragen und wenn ja, gibt es einen neuen Speicherort? Die vorliegende Seite scheint völlig unabhängig von der gegebenen Antwort zu sein.
Christos Hayward
17
Dies beantwortet nicht die Frage mit dem Titel " Using HTML5 ... ".
Ixx
5
@Ixx gut um fair zu sein, das wurde hinzugefügt, nachdem die Antwort veröffentlicht wurde. Trotzdem hast du recht. Die Antwort unten sollte akzeptiert werden
Pekka
17

Einfache Lösung!

<a download="My-FileName.txt" href="data:application/octet-stream,HELLO-WORLDDDDDDDD">Click here</a>

Funktioniert in allen modernen Browsern.

T.Todua
quelle
Hallo, wissen Sie, wie Sie das Attributverhalten "download" mit window.open oder einer anderen Javascript-Funktion festlegen können?
Yucer
2
@yucer Es gibt kein Download-Attribut (oder ein Attribut für diese Angelegenheit) mit window.open(). Es ist irrelevant. Sie können diese Methode verwenden und ein a erzwingen .click(), aber beobachten Sie das Timing, da es Firefox nicht gefällt, wenn Sie aufrufen, .click()bevor Sie das Element an den Körper anhängen lassen.
Brad
Leider werden alle Leerzeichen gelöscht. In meinem Fall ist das wirklich schlecht, da ich Quellcode für eine SVG-Datei herunterladen möchte.
Frankenapps
Leerzeichen bleiben erhalten, wenn Sie encodeURIComponent (Inhalt) verwenden
Mike Redrobe
kann den Namen in Firefox nicht wählen, aber Chrom funktioniert
Bhikkhu Subhuti
10

Sie können einen Daten-URI generieren . Es gibt jedoch browserspezifische Einschränkungen.

Matthew Flaschen
quelle
1
Das ist interessant. Ich werde mehr darüber nachdenken, wenn ich die Gelegenheit dazu bekomme. Vielen Dank!
Toji
@quantumpotato, das tatsächliche Generieren der URL ist etwas schwierig zu erklären. Das Wesentliche ist in RFC 2397 enthalten . Sie können Tools wie nutzen diese für die Prüfung. Anschließend können Sie für Ihre echte App nach einem Daten-URI oder einer Basis-64-Bibliothek für Ihre Sprache suchen. Wenn Sie es nicht finden, können Sie gerne eine Folgefrage stellen. Einige der browserspezifischen Einschränkungen sind im Wikipedia- Artikel aufgeführt . Beispielsweise begrenzt der IE die Länge und den Typ (z. B. nicht Text / HTML).
Matthew Flaschen
Das Generieren von Daten-URLs ist nicht so schwierig: "data:text/plain;charset=UTF-8,"+encodeURIComponent(text)Aber ja, der IE begrenzt die Größe von Daten-URLs auf eine unbrauchbare Menge und unterstützt sie nicht für Dinge wie window.open(...)oder iframes (glaube ich).
Panzi
@panzi, so einfach ist das auch nicht. Zum einen ist dies weder für Collada noch für JSON der richtige MIME-Typ.
Matthew Flaschen
zu nicht informative Antwort. Bitte fügen Sie die Spezifikationen für Browser hinzu, wenn Sie diese erwähnen.
T.Todua
10

Ich habe FileSaver ( https://github.com/eligrey/FileSaver.js ) verwendet und es funktioniert einwandfrei .
Zum Beispiel habe ich diese Funktion ausgeführt, um auf einer Seite angezeigte Protokolle zu exportieren.
Sie müssen ein Array für die Instanziierung des Blobs übergeben, also habe ich das vielleicht nicht richtig geschrieben, aber es funktioniert für mich.
Nur für den Fall, seien Sie vorsichtig mit dem Ersetzen: Dies ist die Syntax, um dies global zu machen, andernfalls wird nur die erste ersetzt, die er trifft.

exportLogs : function(){
    var array = new Array();

    var str = $('#logs').html();
    array[0] = str.replace(/<br>/g, '\n\t');

    var blob = new Blob(array, {type: "text/plain;charset=utf-8"});
    saveAs(blob, "example.log");
}
Razakhel
quelle
2
FileSaver ist großartig, hier ist ein IE Shim für die PreIE10SaveAs-Funktion vor IE10: (Dateiname, Dateinhalt, Mimetyp) {var w = window.open (); var doc = w.document; doc.open (Mimetyp, 'ersetzen'); doc.charset = "utf-8"; doc.write (Filecontent); doc.close (); doc.execCommand ("SaveAs", null, Dateiname); }
aqm
Eine Warnung zu @ aqms Shim: Es werden Skript-Tags ausgeführt.
GameFreak
Auch kann es wünschenswert sein, w.close();nach demexecCommand
GameFreak
8

Ich habe zwei einfache Ansätze gefunden, die für mich funktionieren. Verwenden Sie zunächst ein bereits angeklicktes aElement und fügen Sie die Download-Daten ein. Und zweitens: Generieren eines aElements mit den Download-Daten, Ausführen a.click()und erneutes Entfernen. Der zweite Ansatz funktioniert jedoch nur, wenn er auch von einer Benutzerklickaktion aufgerufen wird. (Einige) Browser blockieren click()aus anderen Kontexten wie beim Laden oder werden nach einem Timeout ausgelöst (setTimeout).

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript">
      function linkDownload(a, filename, content) {
        contentType =  'data:application/octet-stream,';
        uriContent = contentType + encodeURIComponent(content);
        a.setAttribute('href', uriContent);
        a.setAttribute('download', filename);
      }
      function download(filename, content) {
        var a = document.createElement('a');
        linkDownload(a, filename, content);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
    </script>
   </head>
  <body>
    <a href="#" onclick="linkDownload(this, 'test.txt', 'Hello World!');">download</a>
    <button onclick="download('test.txt', 'Hello World!');">download</button>
  </body>
</html>
maikel
quelle
2
Sie können adas Dokument auch in das Dokument einfügen (möglicherweise mit "display:none"), darauf klicken und es dann entfernen.
Teepeemm
1
würde dies in Browsern funktionieren, in denen das Download-Attribut nicht unterstützt wird, wie selbst moderne, dh Safari .. caniuse.com/#feat=download
Muhammad Umer
1
Gerade Safari 5.0 unter Wein getestet. Die erste Version funktioniert, die zweite nicht. Ich habe auch IE 8 (Wein) getestet und es funktioniert nicht.
Maikel
6

Hier ist ein Link zu der Daten-URI-Methode, die Mathew vorgeschlagen hat. Sie hat auf Safari funktioniert, aber nicht gut, da ich den Dateityp nicht festlegen konnte. Sie wird als "unbekannt" gespeichert. Dann muss ich später erneut dorthin gehen und die Reihenfolge ändern um die Datei anzuzeigen ...

http://www.nihilogic.dk/labs/canvas2image/

Dennkster
quelle
4

Sie können localStorage verwenden. Dies ist das HTML5-Äquivalent von Cookies. Es scheint unter Chrome und Firefox zu funktionieren, ABER unter Firefox musste ich es auf einen Server hochladen. Das heißt, das Testen direkt auf meinem Heimcomputer hat nicht funktioniert.

Ich arbeite an HTML5-Beispielen. Gehen Sie zu http://faculty.purchase.edu/jeanine.meyer/html5/html5explain.html und scrollen Sie zum Labyrinth. Die Informationen zum Wiederherstellen des Labyrinths werden mithilfe von localStorage gespeichert.

Ich bin zu diesem Artikel gekommen und habe nach HTML5-JavaScript zum Laden und Arbeiten mit XML-Dateien gesucht. Ist es das gleiche wie älteres HTML und JavaScript ????

Jeanine
quelle
4

Versuchen

let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent('"My DATA"');
a.download = 'myFile.json';
a.click(); // we not add 'a' to DOM so no need to remove

Wenn Sie Binärdaten herunterladen möchten, klicken Sie hier

Aktualisieren

2020.06.14 Ich aktualisiere Chrome auf 83.0 und höher. SO-Snippet-Stopp funktioniert (aufgrund von Sandbox-Sicherheitsbeschränkungen ) - aber die JSFiddle-Version funktioniert hier

Kamil Kiełczewski
quelle
3

Wie bereits erwähnt, können die Datei- API zusammen mit den FileWriter- und FileSystem- APIs verwendet werden, um Dateien auf dem Computer eines Clients über den Kontext einer Browser-Registerkarte / eines Browser-Fensters zu speichern.

Es gibt jedoch einige Dinge im Zusammenhang mit den beiden letztgenannten APIs, die Sie beachten sollten:

  • Implementierungen der APIs sind derzeit nur in Chromium-basierten Browsern (Chrome & Opera) vorhanden.
  • Beide APIs wurden am 24. April 2014 vom W3C-Standard-Track entfernt und sind ab sofort proprietär
  • Das Entfernen der (jetzt proprietären) APIs aus zukünftigen Implementierungsbrowsern ist möglich
  • Eine Sandbox (ein Speicherort auf der Festplatte, außerhalb dessen Dateien keine Auswirkungen haben können) wird zum Speichern der mit den APIs erstellten Dateien verwendet
  • Ein virtuelles Dateisystem (eine Verzeichnisstruktur, die nicht unbedingt in derselben Form auf der Festplatte vorhanden ist wie beim Zugriff über den Browser) repräsentiert die mit den APIs erstellten Dateien

Hier sind einfache Beispiele dafür, wie die APIs direkt und indirekt zusammen verwendet werden, um dies zu tun:

BakedGoods *

bakedGoods.get({
        data: ["testFile"],
        storageTypes: ["fileSystem"],
        options: {fileSystem:{storageType: Window.PERSISTENT}},
        complete: function(resultDataObj, byStorageTypeErrorObj){}
});

Verwenden der Rohdatei-, FileWriter- und FileSystem-APIs

function onQuotaRequestSuccess(grantedQuota)
{

    function saveFile(directoryEntry)
    {

        function createFileWriter(fileEntry)
        {

            function write(fileWriter)
            {
                var dataBlob = new Blob(["Hello world!"], {type: "text/plain"});
                fileWriter.write(dataBlob);              
            }

            fileEntry.createWriter(write);
        }

        directoryEntry.getFile(
            "testFile", 
            {create: true, exclusive: true},
            createFileWriter
        );
    }

    requestFileSystem(Window.PERSISTENT, grantedQuota, saveFile);
}

var desiredQuota = 1024 * 1024 * 1024;
var quotaManagementObj = navigator.webkitPersistentStorage;
quotaManagementObj.requestQuota(desiredQuota, onQuotaRequestSuccess);

Obwohl die FileSystem- und FileWriter-APIs nicht mehr auf der Standardspur sind, kann ihre Verwendung meiner Meinung nach in einigen Fällen gerechtfertigt sein, weil:

  • Erneutes Interesse der nicht implementierenden Browser-Anbieter kann sie direkt wieder darauf setzen
  • Die Marktdurchdringung bei der Implementierung von (Chromium-basierten) Browsern ist hoch
  • Google (der Hauptverursacher von Chromium) hat den APIs kein Datum für das Ende der Lebensdauer angegeben

Ob "einige Fälle" Ihre eigenen umfassen, müssen Sie jedoch selbst entscheiden.

* BakedGoods wird von niemand anderem als diesem Kerl hier gepflegt :)

Kevin
quelle
2

Dieser Thread war von unschätzbarem Wert, um herauszufinden, wie eine Binärdatei generiert und die benannte Datei heruntergeladen werden kann, alles im Client-Code ohne Server.

Der erste Schritt für mich war das Generieren des binären Blobs aus Daten, die ich gespeichert habe. Es gibt viele Beispiele dafür für einen einzelnen Binärtyp. In meinem Fall habe ich ein Binärformat mit mehreren Typen, die Sie als Array übergeben können, um den Blob zu erstellen.

saveAnimation: function() {

    var device = this.Device;
    var maxRow = ChromaAnimation.getMaxRow(device);
    var maxColumn = ChromaAnimation.getMaxColumn(device);
    var frames = this.Frames;
    var frameCount = frames.length;

    var writeArrays = [];


    var writeArray = new Uint32Array(1);
    var version = 1;
    writeArray[0] = version;
    writeArrays.push(writeArray.buffer);
    //console.log('version:', version);


    var writeArray = new Uint8Array(1);
    var deviceType = this.DeviceType;
    writeArray[0] = deviceType;
    writeArrays.push(writeArray.buffer);
    //console.log('deviceType:', deviceType);


    var writeArray = new Uint8Array(1);
    writeArray[0] = device;
    writeArrays.push(writeArray.buffer);
    //console.log('device:', device);


    var writeArray = new Uint32Array(1);
    writeArray[0] = frameCount;
    writeArrays.push(writeArray.buffer);
    //console.log('frameCount:', frameCount);

    for (var index = 0; index < frameCount; ++index) {

      var frame = frames[index];

      var writeArray = new Float32Array(1);
      var duration = frame.Duration;
      if (duration < 0.033) {
        duration = 0.033;
      }
      writeArray[0] = duration;
      writeArrays.push(writeArray.buffer);

      //console.log('Frame', index, 'duration', duration);

      var writeArray = new Uint32Array(maxRow * maxColumn);
      for (var i = 0; i < maxRow; ++i) {
        for (var j = 0; j < maxColumn; ++j) {
          var color = frame.Colors[i][j];
          writeArray[i * maxColumn + j] = color;
        }
      }
      writeArrays.push(writeArray.buffer);
    }

    var blob = new Blob(writeArrays, {type: 'application/octet-stream'});

    return blob;
}

Der nächste Schritt besteht darin, den Browser zu veranlassen, den Benutzer aufzufordern, diesen Blob mit einem vordefinierten Namen herunterzuladen.

Ich brauchte nur einen benannten Link, den ich in HTML5 hinzugefügt hatte und den ich wiederverwenden konnte, um den ursprünglichen Dateinamen umzubenennen. Ich habe es versteckt gehalten, da der Link nicht angezeigt werden muss.

<a id="lnkDownload" style="display: none" download="client.chroma" href="" target="_blank"></a>

Der letzte Schritt besteht darin, den Benutzer zum Herunterladen der Datei aufzufordern.

var data = animation.saveAnimation();
var uriContent = URL.createObjectURL(data);
var lnkDownload = document.getElementById('lnkDownload');
lnkDownload.download = 'theDefaultFileName.extension';
lnkDownload.href = uriContent;
lnkDownload.click();
tgraupmann
quelle
1

Hier ist ein Tutorial zum Exportieren von Dateien als ZIP:

Bevor Sie beginnen, gibt es eine Bibliothek zum Speichern von Dateien. Der Name der Bibliothek lautet fileSaver.js. Diese Bibliothek finden Sie hier. Beginnen wir jetzt mit den erforderlichen Bibliotheken:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"  type="text/javascript"></script>
<script type="text/javascript" src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.js" ></script>

Kopieren Sie nun diesen Code und dieser Code lädt eine Zip-Datei mit einer Datei hello.txt mit Inhalt Hello World herunter. Wenn alles gut funktioniert, wird eine Datei heruntergeladen.

<script type="text/javascript">
    var zip = new JSZip();
    zip.file("Hello.txt", "Hello World\n");
    zip.generateAsync({type:"blob"})
    .then(function(content) {
        // see FileSaver.js
        saveAs(content, "file.zip");
    });
</script>

Dadurch wird eine Datei namens file.zip heruntergeladen. Weitere Informationen finden Sie hier: http://www.wapgee.com/story/248/guide-to-create-zip-files-using-javascript-by-using-jszip-library

Ilyas Karim
quelle