Korzystanie z HTML5 / JavaScript do generowania i zapisywania pliku

317

Ostatnio bawię się WebGL i uruchomiłem czytnik Collada. Problem jest dość powolny (Collada to bardzo szczegółowy format), więc zacznę konwertować pliki do łatwiejszego w użyciu formatu (prawdopodobnie JSON). Mam już kod do parsowania pliku w JavaScript, więc równie dobrze mogę go użyć jako mojego eksportera! Problem polega na oszczędzaniu.

Teraz wiem, że mogę przeanalizować plik, wysłać wynik na serwer i poprosić przeglądarkę o przesłanie pliku z powrotem do serwera w celu pobrania. Ale w rzeczywistości serwer nie ma nic wspólnego z tym konkretnym procesem, więc po co się w to angażować? Mam już zawartość żądanego pliku w pamięci. Czy jest jakiś sposób, aby przedstawić użytkownikowi plik do pobrania przy użyciu czystego JavaScript? (Wątpię, ale równie dobrze mogę zapytać ...)

Żeby było jasne: nie próbuję uzyskać dostępu do systemu plików bez wiedzy użytkowników! Użytkownik dostarczy plik (prawdopodobnie metodą przeciągnij i upuść), skrypt przekształci plik w pamięci, a użytkownik zostanie poproszony o pobranie wyniku. Wszystko to powinno być „bezpiecznymi” działaniami, jeśli chodzi o przeglądarkę.

[EDYCJA]: Nie wspomniałem o tym z góry, więc plakaty, które odpowiedziały na „Flash” są wystarczająco ważne, ale częścią tego, co robię, jest próba podkreślenia, co można zrobić za pomocą czystego HTML5 ... więc Flash jest wprost w moim przypadku. (Chociaż jest to całkowicie poprawna odpowiedź dla każdego, kto robi „prawdziwą” aplikację internetową). W takim przypadku wygląda na to, że nie mam szczęścia, chyba że chcę zaangażować serwer. W każdym razie dzięki!

Toji
źródło
8
Możesz rozważyć zmianę zaakceptowanej odpowiedzi, wydaje się, że jest teraz sposób czysto HTML
Pekka

Odpowiedzi:

256

OK, tworzenie danych: URI zdecydowanie mi pomaga, dzięki Matthew i Dennksterowi wskazując tę ​​opcję! Oto w zasadzie jak to robię:

1) przekształć całą treść w ciąg o nazwie „content” (np. Najpierw ją tam tworząc lub czytając innerHTML tagu już zbudowanej strony).

2) Zbuduj identyfikator URI danych:

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

Będą ograniczenia długości w zależności od typu przeglądarki itp., Ale np. Firefox 3.6.12 działa do co najmniej 256 KB. Zamiast tego kodowanie w Base64 przy użyciu encodeURIComponent może sprawić, że wszystko będzie bardziej wydajne, ale dla mnie to było w porządku.

3) otwórz nowe okno i „przekieruj” do tego identyfikatora URI monituje o lokalizację pobierania mojej strony wygenerowanej w JavaScript:

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

Otóż ​​to.

Nie
źródło
34
Jeśli chcesz uniknąć używania wyskakującego okienka, które może zostać zablokowane, możesz ustawić location.hrefzawartość. location.href = uriContent.
Alex Turpin
12
Cześć, próbowałem tego, ale pobiera plik jako plik .part. Jak mogę ustawić typ pliku?
Sedat Başar
6
@ SedatBaşar URI danych nie obsługują ustawiania nazwy pliku, musisz polegać na ustawieniu odpowiedniego rozszerzenia w przeglądarce przy użyciu typu MIME. Ale jeśli typ MIME może być renderowany przez przeglądarkę, nie pobierze go, ale wyświetli. Istnieje kilka innych sposobów, ale nie działa w IE <10.
panzi
7
IE tak naprawdę nie obsługuje identyfikatorów URI danych, a Firefox wydaje się zapisywać pliki pod losową nazwą.
nylund
25
Myślę, że utrudniamy to, niż to konieczne. Otwórz konsolę JS na tej stronie i umieść ją location.href = "data:application/octet-stream," + encodeURIComponent(jQuery('#answer-4551467 .post-text').first().text());, aby zapisać treść odpowiedzi @ Nøk w pliku. Nie mam IE, żeby to przetestować, ale działa dla webkita.
Bruno Bronosky
278

Proste rozwiązanie dla przeglądarek obsługujących HTML5 ...

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

Stosowanie

download('test.txt', 'Hello world!');
Matěj Pokorný
źródło
2
Jeśli znasz źródłowy adres URL, który chcesz pobrać, jest to najlepsze rozwiązanie!
sidonaldson,
31
Możliwość ustawienia nazwy pliku czyni to zwycięzcą.
Omn
9
Ta metoda działała w Chrome do ostatniej aktualizacji, którą otrzymałem kilka dni temu (35.0.1916.114 m). Teraz działa częściowo, ponieważ nazwa pliku i rozszerzenie nie działają (zawsze nazywa plik download.txt niezależnie od tego, co zostało przekazane.)
Sevin7
6
Mam Chrom 42.0.2311.90 i działa to dla mnie z oczekiwaną nazwą pliku.
Saurabh Kumar
4
Czy istnieje ograniczenie ilości danych, które można uwzględnić?
Kaspar Lee
80

HTML5 zdefiniował window.saveAs(blob, filename)metodę. Obecnie nie jest obsługiwany przez żadną przeglądarkę. Ale istnieje biblioteka kompatybilności o nazwie FileSaver.js, która dodaje tę funkcję do większości współczesnych przeglądarek (w tym Internet Explorer 10+). Internet Explorer 10 obsługuje navigator.msSaveBlob(blob, filename)metodę ( MSDN ), która jest używana w FileSaver.js do obsługi Internet Explorera.

Napisałem post na blogu z dalszymi szczegółami na temat tego problemu.

panzi
źródło
1
Co z blokowaniem wyskakujących okienek? Zachowanie tej biblioteki jest podobne do rozwiązania @ Nøk. Zwykły tekst w przeglądarce Firefox zostanie otwarty w nowym. Tylko Chrome próbuje go zapisać, ale zmienia rozszerzenie (potrzebuję pliku kropkowego bez rozszerzenia).
ciembor
1
@ciembor wariant atrybutu pobierania (URL obiektu +) (którego używam z chrome) pozwala ustawić nazwę pliku. Działa dla mnie w chromie.
panzi
1
@ciembor aha i wyskakujące okienko nie jest blokowane, jeśli kliknięcie spowodowało to bezpośrednio.
panzi
6
FileSaver.js obsługuje teraz IE
Eli Gray
15
W3C mówi: Prace nad tym dokumentem zostały przerwane i nie należy się do niego odwoływać ani wykorzystywać go jako podstawy do wdrożenia.
WaiKit Kung
48

Zapisywanie dużych plików

Długie identyfikatory URI mogą powodować problemy z wydajnością w przeglądarkach. Inną opcją zapisywania plików generowanych po stronie klienta jest umieszczenie ich zawartości w obiekcie Blob (lub pliku) i utworzenie łącza pobierania za pomocąURL.createObjectURL(blob) . Zwraca adres URL, którego można użyć do pobrania zawartości obiektu blob. Obiekt blob jest przechowywany w przeglądarce, dopóki nie URL.revokeObjectURL()zostanie wywołany w adresie URL lub dokument, który go utworzył, zostanie zamknięty. Większość przeglądarek internetowych obsługuje adresy URL obiektów , Opera Mini jest jedyną, która ich nie obsługuje.

Wymuszanie pobierania

Jeśli dane to tekst lub obraz, przeglądarka może otworzyć plik zamiast zapisywać go na dysku. Aby spowodować pobranie pliku po kliknięciu łącza, możesz użyć downloadatrybutu. Jednak nie wszystkie przeglądarki internetowe obsługują atrybut pobierania . Inną opcją jest użycie application/octet-streamjako typu MIME pliku, ale powoduje to, że plik jest przedstawiany jako binarny obiekt blob, co jest szczególnie nieprzyjazne dla użytkownika, jeśli nie podasz nazwy pliku lub nie możesz jej podać. Zobacz także „ Wymuś otwarcie okna„ Zapisz jako ... ”otwieranie przy kliknięciu linku tekstowego dla pdf w HTML ”.

Określanie nazwy pliku

Jeśli obiekt blob został utworzony za pomocą konstruktora plików, można również ustawić nazwę pliku, ale tylko kilka przeglądarek internetowych (w tym Chrome i Firefox) obsługuje konstruktor plików . Nazwę pliku można również podać jako argument downloadatrybutu, ale wymaga to wielu względów bezpieczeństwa . Internet Explorer 10 i 11 udostępnia własną metodę msSaveBlob , która określa nazwę pliku.

Przykładowy kod

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
źródło
1
Czy mogę wyświetlić okno dialogowe (wyskakujące okienko) określające folder (katalog) do zapisania pliku?
Calvin
@ Calvin: Zaktualizowałem odpowiedź, aby wyjaśnić, jak wymusić pobranie i podać nazwę pliku. Wydaje mi się, że w przypadku przeglądarki IE można msSaveBlobotworzyć okno dialogowe „Zapisz jako”. W przypadku innych przeglądarek jedyną opcją jest ręczne wybranie opcji „Zapisz jako” z menu kontekstowego łącza pobierania.
bcmpinc
1
@ Jek-fdrv: W przeglądarce Safari działają tylko adresy URL obiektów blob. Atrybut pobierania i konstruktor plików nie są obsługiwane przez Safari, więc nie można wymusić pobierania, co oznacza, że ​​obiekt blob prawdopodobnie zostanie otwarty w samej przeglądarce i nie można podać nazwy pliku. W podanym przykładzie nadal powinno być możliwe pobranie pliku za pomocą Safari za pomocą menu kontekstowego łącza.
bcmpinc
To bardzo pomocna i pouczająca odpowiedź. Jeszcze jedna rzecz, która może pomóc ludziom takim jak ja: po ustawieniu document.getElementById('link').href = url;twój kod może iść dalej i odpalić link używając metody elementu .click().
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
źródło
3
Jaki jest efekt contentType? Do czego jest to używane?
Uri
3
Ten działa dobrze nawet w najnowszym Chrome, w przeciwieństwie do odpowiedzi @ Matěj Pokorný. Dzięki.
Alexander Amelkin,
2
To nie działa dla mnie na FF36 lub IE11. Jeśli zastąpię a.clickkod za pomocą, document.createEvent()jak sugerował Matěj Pokorný, działa na FF, ale nie na IE. Nie próbowałem Chrome.
Peter Hull,
25

Aby to zrobić, spójrz na Downloadify Douga Neinera, który jest interfejsem JavaScript opartym na technologii Flash.

Downloadify to niewielka biblioteka JavaScript + Flash, która umożliwia generowanie i zapisywanie plików w locie, w przeglądarce, bez interakcji z serwerem.

Pekka
źródło
6
Dla większości ludzi jest to prawdopodobnie odpowiedź, której będą potrzebować. Tak więc, mimo że nie spełnia moich konkretnych wymagań (jak wyjaśniono powyżej), zaznaczam to jako zaakceptowaną odpowiedź.
Toji
2
@Toji ah, rozumiem. Może ponownie zapytaj i przepisz pod HTML 5sztandarem i odpowiednio otaguj? Prawdopodobnie przyciągnęłoby to tych użytkowników, którzy wiedzą o tym konkretnym polu (jak sądzę, wciąż jest to stosunkowo niewielki tłum). Jestem prawie pewien, że można to zrobić w HTML 5, ale nie mam pojęcia, jak to zrobić.
Pekka
1
Czy domena downloadify downloadify.info została kupiona / przeniesiona, a jeśli tak, to czy jest nowa lokalizacja? Obecna strona wydaje się całkowicie niezwiązana z udzieloną odpowiedzią.
Christos Hayward
17
To nie odbierze Korzystanie HTML5 ... - pt pytanie.
Ixx
5
@ Cóż, muszę być uczciwy, który został dodany po opublikowaniu odpowiedzi. Nadal masz rację. Poniższa odpowiedź powinna zostać zaakceptowana
Pekka
17

Proste rozwiązanie!

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

Działa we wszystkich nowoczesnych przeglądarkach.

T.Todua
źródło
Cześć, czy wiesz, jak określić zachowanie atrybutu „pobieranie” za pomocą window.open lub innej funkcji javascript?
Yumper
2
@yucer Nie ma atrybutu pobierania (ani żadnego atrybutu w tym zakresie) z window.open(). To nie ma znaczenia. Możesz użyć tej metody i wymusić .click()na niej, ale uważaj na czas, ponieważ Firefox nie lubi tego, jeśli zadzwonisz, .click()zanim pozwoli elementowi dołączyć się do ciała.
Brad
Ale niestety wszystkie spacje zostaną usunięte. W moim przypadku jest to naprawdę złe, ponieważ chcę pobrać kod źródłowy pliku SVG.
frankenapps
spacje zostaną zachowane, jeśli użyjesz encodeURIComponent (content)
Mike Redrobe
nie można wybrać nazwy w firefoxie, ale chrome działa
Bhikkhu Subhuti
10

Możesz wygenerować identyfikator URI danych . Istnieją jednak ograniczenia specyficzne dla przeglądarki.

Matthew Flaschen
źródło
1
To jest interesujące. Przyjrzę się temu bardziej, kiedy będę miał szansę. Dzięki!
Toji
@quantumpotato, generowanie adresu URL jest trochę trudne do wyjaśnienia. Wszystkie szczegóły są w RFC 2397 . Można użyć narzędzia, takie jak to do testowania. Następnie dla swojej prawdziwej aplikacji możesz wyszukać identyfikator URI danych lub bibliotekę base 64 dla swojego języka. Jeśli go nie znajdziesz, zadaj pytanie uzupełniające. Niektóre ograniczenia specyficzne dla przeglądarki podano w artykule w Wikipedii . Na przykład IE ogranicza długość i typ (np. Nie tekst / HTML).
Matthew Flaschen
Generowanie adresów URL danych nie jest takie trudne: "data:text/plain;charset=UTF-8,"+encodeURIComponent(text)ale tak, IE ogranicza rozmiar adresów URL danych do nieużytecznej ilości i nie obsługuje ich dla rzeczy takich jak window.open(...)iframe (myślę).
panzi
@panzi, to też nie jest takie proste. Po pierwsze, nie jest to odpowiedni typ MIME dla Collady lub JSON.
Matthew Flaschen
zbyt nieinformacyjna odpowiedź. dodaj specyfikacje dla przeglądarek, jeśli je wymienisz.
T.Todua
10

Użyłem FileSaver ( https://github.com/eligrey/FileSaver.js ) i działa dobrze.
Na przykład wykonałem tę funkcję, aby wyeksportować dzienniki wyświetlane na stronie.
Musisz podać tablicę dla instancji Blob, więc może po prostu nie napisałem tego we właściwy sposób, ale to działa dla mnie.
Na wszelki wypadek zachowaj ostrożność przy zamianie: jest to składnia umożliwiająca uczynienie tego globalnym, w przeciwnym razie zastąpi on tylko pierwszego, którego spotka.

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
źródło
2
FileSaver jest świetny, oto IE Shim dla funkcji sprzed IE10 preIE10SaveAs: (nazwa pliku, plik-plik, typ mimetyczny) {var w = window.open (); var doc = w.document; doc.open (typ mimetyczny, „zamień”); doc.charset = "utf-8"; doc.write (zawartość pliku); doc.close (); doc.execCommand („SaveAs”, null, nazwa pliku); }
aqm
Ostrzeżenie przed podkładką @ aqm: Wykonuje tagi skryptu.
GameFreak,
Również może być pożądane umieszczenie w.close();poexecCommand
GameFreak
8

Znalazłem dwa proste podejścia, które działają dla mnie. Po pierwsze, użycie już klikniętego aelementu i wstrzyknięcie pobranych danych. Po drugie, generowanie aelementu z pobranymi danymi, wykonywanie a.click()i usuwanie go ponownie. Ale drugie podejście działa tylko wtedy, gdy wywoływane jest również przez akcję kliknięcia użytkownika. (Niektóre) Blok przeglądarki click()z innych kontekstów, takich jak ładowanie lub uruchamiany po upływie limitu czasu (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
źródło
2
Możesz także wstawić adokument do dokumentu (ewentualnie za pomocą "display:none"), kliknąć go, a następnie usunąć.
Teepeemm
1
czy działałoby to w przeglądarkach, w których atrybut pobierania nie jest obsługiwany, np. nawet w wersji współczesnej i safari… caniuse.com/#feat=download
Muhammad Umer
1
Właśnie przetestowałem Safari 5.0 pod winem. Pierwsza wersja działa, druga nie. Testowałem również IE 8 (wino) i to nie działa.
maikel
6

Oto link do metody URI danych Mathew zasugerował, że działał na safari, ale nie dobrze, ponieważ nie mogłem ustawić rodzaju pliku, jest zapisywany jako „nieznany”, a następnie muszę tam wrócić później i zmienić go w kolejności aby wyświetlić plik ...

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

Dennkster
źródło
4

Możesz użyć localStorage. Jest to odpowiednik plików cookie HTML5. Wygląda na to, że działa w Chrome i Firefox ALE w Firefoksie, musiałem przesłać go na serwer. Oznacza to, że testowanie bezpośrednio na moim komputerze domowym nie działało.

Pracuję nad przykładami HTML5. Przejdź do http://faculty.purchase.edu/jeanine.meyer/html5/html5explain.html i przewiń do labiryntu. Informacje do przebudowania labiryntu są przechowywane za pomocą localStorage.

Przyszedłem do tego artykułu, szukając kodu JavaScript HTML5 do ładowania i pracy z plikami xml. Czy to to samo, co starszy HTML i JavaScript?

Jeanine
źródło
4

próbować

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

Jeśli chcesz pobrać dane binarne, spójrz tutaj

Aktualizacja

2020.06.14 Aktualizuję Chrome do wersji 83.0 i nowszej SO zatrzymanie fragmentu kodu SO (ze względu na ograniczenia bezpieczeństwa piaskownicy ) - ale działa wersja JSFiddle - tutaj

Kamil Kiełczewski
źródło
3

Jak wspomniano wcześniej, interfejs API File wraz z interfejsami FileWriter i FileSystem API może służyć do przechowywania plików na komputerze klienta w kontekście karty / okna przeglądarki.

Jest jednak kilka rzeczy związanych z dwoma ostatnimi interfejsami API, o których powinieneś wiedzieć:

  • Implementacje interfejsów API istnieją obecnie tylko w przeglądarkach opartych na Chromium (Chrome i Opera)
  • Oba interfejsy API zostały usunięte ze standardowej ścieżki W3C 24 kwietnia 2014 r. I na dzień dzisiejszy są zastrzeżone
  • Możliwe jest usunięcie (obecnie zastrzeżonych) interfejsów API z implementacji przeglądarek w przyszłości
  • W celu przechowywania plików utworzonych za pomocą interfejsów API używana jest piaskownica (lokalizacja na dysku, na której pliki nie mogą dać żadnego efektu)
  • Wirtualny system plików (struktura katalogów, które niekoniecznie istnieje na dysku w tej samej formie, że nie kiedy dostęp z poziomu przeglądarki) jest używany reprezentują plików utworzonych za pomocą interfejsów API

Oto proste przykłady wykorzystania interfejsów API, bezpośrednio i pośrednio, w tym celu:

BakedGoods *

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

Korzystanie z nieprzetworzonych interfejsów API File, FileWriter i FileSystem

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

Chociaż interfejsy API FileSystem i FileWriter nie są już na ścieżce standardów, ich użycie może być uzasadnione w niektórych przypadkach, moim zdaniem, ponieważ:

  • Ponowne zainteresowanie ze strony niewdrożących dostawców przeglądarek może przywrócić ich do życia
  • Penetracja rynku implementacji przeglądarek (opartych na chromie) jest wysoka
  • Google (główny współtwórca Chromium) nie podał interfejsów API daty zakończenia

Jednak to, czy „niektóre przypadki” obejmują twoje, należy do ciebie.

* BakedGoods jest utrzymywany przez nikogo innego niż ten facet tutaj :)

Kevin
źródło
2

Wątek ten był nieoceniony, aby dowiedzieć się, jak wygenerować plik binarny i poprosić o pobranie nazwanego pliku, wszystko w kodzie klienta bez serwera.

Pierwszym krokiem było wygenerowanie binarnego obiektu blob z danych, które zapisywałem. Istnieje wiele próbek do zrobienia tego dla pojedynczego typu binarnego, w moim przypadku mam format binarny z wieloma typami, które można przekazać jako tablicę do utworzenia obiektu blob.

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

Następnym krokiem jest skłonienie przeglądarki do monitowania użytkownika o pobranie tego obiektu blob o wstępnie zdefiniowanej nazwie.

Wszystko, czego potrzebowałem, to nazwany link, który dodałem w HTML5, którego mógłbym użyć ponownie, aby zmienić nazwę początkowej nazwy pliku. Ukryłem go, ponieważ link nie wymaga wyświetlania.

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

Ostatnim krokiem jest zachęcenie użytkownika do pobrania pliku.

var data = animation.saveAnimation();
var uriContent = URL.createObjectURL(data);
var lnkDownload = document.getElementById('lnkDownload');
lnkDownload.download = 'theDefaultFileName.extension';
lnkDownload.href = uriContent;
lnkDownload.click();
tgraupmann
źródło
1

Oto samouczek dotyczący eksportowania plików jako ZIP:

Zanim zaczniesz, istnieje biblioteka do zapisywania plików, nazwa biblioteki to fileSaver.js, możesz znaleźć tę bibliotekę tutaj. Zacznijmy teraz, dołącz wymagane biblioteki:

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

Teraz skopiuj ten kod, a ten kod pobierze plik zip z plikiem hello.txt o treści Hello World. Jeśli wszystko działa poprawnie, plik zostanie pobrany.

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

Spowoduje to pobranie pliku o nazwie file.zip. Możesz przeczytać więcej tutaj: http://www.wapgee.com/story/248/guide-to-create-zip-files-using-javascript-by-using-jszip-library

Ilyas Karim
źródło