Pobierz plik adresu URL danych

127

Bawię się pomysłem stworzenia całkowicie opartego na JavaScript narzędzia do zip / unzip, do którego każdy może uzyskać dostęp z przeglądarki. Mogą po prostu przeciągnąć plik zip bezpośrednio do przeglądarki, co pozwoli im pobrać wszystkie pliki. Mogą również tworzyć nowe pliki zip, przeciągając pojedyncze pliki do.

Wiem, że lepiej byłoby zrobić to na serwerze, ale ten projekt jest tylko dla odrobiny zabawy.

Przeciąganie plików do przeglądarki powinno być łatwe, jeśli skorzystam z różnych dostępnych metod. (Styl Gmail)

Miejmy nadzieję, że kodowanie / dekodowanie powinno być w porządku. Widziałem kilka bibliotek as3 zip, więc jestem pewien, że powinienem być w porządku.

Moim problemem jest pobieranie plików na końcu.

window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....' 

działa to dobrze w firefox, ale nie w chrome.

Mogę osadzać pliki jako obrazy dobrze w chrome używając <img src="data:jpg/image;ba.." />, ale pliki niekoniecznie muszą być obrazami. Mogą mieć dowolny format.

Czy ktoś może wymyślić inne rozwiązanie lub jakieś obejście?

Mikee
źródło
Obecne wsparcie jest niestety dość ograniczone
Casebash

Odpowiedzi:

42

Pomysły:

  • Wypróbuj <a href="data:...." target="_blank">(nieprzetestowane)

  • Użyj downloadify zamiast adresów URL danych (zadziała również dla IE)

Pekka
źródło
@jcubic dzięki za wskazanie martwego linku. Wydaje się, że nowa lokalizacja pobierania to github.com/dcneiner/Downloadify
Pekka
Jeśli nie możesz używać Flasha, ale używasz komponentu Java po stronie serwera, możesz użyć tego: github.com/suprememoocow/databounce . Używa serwletu do „odbijania” danych od klienta. Byłoby dość łatwo wykonać tę samą sztuczkę w innych technologiach serwerowych, takich jak Python, ASP.NET itp.
Andrew Newdigate,
Czy można to zrobić bez flasha? Adres URL danych dla wszystkich przeglądarek oprócz IE i jakiegoś rodzaju ActiveX foo dla IE? (W ten sposób udało mi się odtwarzać muzykę bez Flasha: dźwięk HTML5 dla wszystkich przeglądarek oprócz IE i ActiveX dla IE.)
panzi
Downloadify oczekuje odtwarzacza Flash w przeglądarce. Jeśli użytkownik nie ma odtwarzacza flash, plik nie zostanie pobrany
Jeevanandan J
186

Jeśli chcesz również nadać plikowi sugerowaną nazwę (zamiast domyślnego `` pobierania ''), możesz użyć następujących w Chrome, Firefox i niektórych wersjach IE:

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

A poniższy przykład pokazuje jego użycie:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");
owencm
źródło
6
Możesz to uprościć, używając link.click()zamiast swojej -funkcjieventFire ... jsfiddle.net/ARTsinn/Ezx5m
yckart
3
Niezłe rozwiązanie. ale po co ten link?
webshaker
6
Zmienna „link” wychodzi poza zakres na końcu funkcji (pamiętaj, że nigdy nie dodaliśmy jej do domeny), więc wkrótce potem zostanie usunięta.
owencm
8
Działa to tylko w Chrome. Jeśli chcesz, aby działało w przeglądarce Firefox / IE, spójrz na odpowiedź z @MartinoDino.
TrueWill,
1
Próbowałem z download.js , jak sugerowano tutaj i wydaje się, że działa. :)
joaorodr84
56

function download(dataurl, filename) {
  var a = document.createElement("a");
  a.href = dataurl;
  a.setAttribute("download", filename);
  a.click();
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

lub:

function download(url, filename) {
fetch(url).then(function(t) {
    return t.blob().then((b)=>{
        var a = document.createElement("a");
        a.href = URL.createObjectURL(b);
        a.setAttribute("download", filename);
        a.click();
    }
    );
});
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");

Zibri
źródło
kliknij zdarzenie na nieistniejącym elemencie: D nie ma potrzeby dodawania dziecka.
Zibri
1
tak. możesz po prostu wywołać a.click () po utworzeniu elementu 'a', a następnie ustawić href a.
user1709076
w przeszłości bezpośrednie wywoływanie a.click () nie działało, ale działało ze zdarzeniem. Teraz oboje pracują.
Zibri
1
Działa to w większości nowoczesnych przeglądarek, ale chciałbym zauważyć, że dołączenie do dokumentu, a następnie usunięcie jest konieczne do obsługi niektórych starszych przeglądarek.
owencm
3
Twoje drugie rozwiązanie powinno być używane, gdy dataUri staje się zbyt duża (zależy od przeglądarki, ale Chrome nie akceptuje Uri o wielu megabajtach). Zobacz także stackoverflow.com/questions/38781968/… .
neural5torm
27

Chcę podzielić się moim doświadczeniem i pomóc komuś, kto utknął w pobieranych plikach, które nie działają w Firefoksie i zaktualizowanej odpowiedzi na 2014 rok. Poniższy fragment będzie działał zarówno w przeglądarce Firefox, jak i Chrome i przyjmie nazwę pliku:

  // Construct the <a> element
  var link = document.createElement("a");
  link.download = thefilename;
  // Construct the uri
  var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  // Cleanup the DOM
  document.body.removeChild(link);
Martino Dino
źródło
4
Niestety nie działa w Safari. Wydaje się, że Safari nie rozpoznaje downloadatrybutu. W każdym razie dzięki, to jest tak blisko, jak mogę w tej chwili.
Moritz Petersen
powoduje to przekierowanie okna do wartości href dla mnie w IE 11. prevetDefault (); nie zatrzymuje zachowania w IE
b_dubb
1
Dzięki, także jeśli btoanie jest zdefiniowane (np. W projekcie frontendowym z węzłem) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
Ivan Borshchov
2
usunięcie linku jest bezcelowe, w następnym wierszu wykracza poza zakres i zostanie usunięte z pamięci, nie jest to prawidłowy cel do usunięcia.
macdja38
1
nie ma potrzeby document.body.appendChild ... zobacz moją odpowiedź stackoverflow.com/a/45905238/236062
Zibri
13

Oto czyste rozwiązanie JavaScript, które testowałem, działając w przeglądarkach Firefox i Chrome, ale nie w Internet Explorerze:

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
    delete link;
}

Dotychczas znalezione rozwiązania dla różnych przeglądarek:

downloadify -> Wymaga Flasha

databounce -> Testowane w IE 10 i 11 i nie działa dla mnie. Wymaga serwletu i pewnych dostosowań. (Nieprawidłowo wykrywa nawigator. Musiałem ustawić IE w trybie zgodności, aby przetestować, domyślny zestaw znaków w serwlecie, obiekt opcji JavaScript z poprawną ścieżką do serwletu dla ścieżek bezwzględnych ...) W przypadku przeglądarek innych niż IE otwiera plik w tym samym oknie.

download.js -> http://danml.com/download.html Inna biblioteka podobna, ale nie przetestowana. Twierdzi, że jest czystym JavaScriptem, nie wymaga serwletu ani Flasha, ale nie działa w IE <= 9.

Jezus MC
źródło
download.js jest całkiem niezły. Właśnie zrobiłem szybkie sprawdzenie IE11, to działa. Wielkie dzięki!
Ricky Jiao
12

Istnieje kilka rozwiązań, ale zależą one od HTML5 i nie zostały jeszcze w pełni zaimplementowane w niektórych przeglądarkach. Poniższe przykłady zostały przetestowane w Chrome i Firefox (częściowo działa).

  1. Przykład płótna z obsługą zapisywania do pliku. Po prostu ustaw swój document.location.hrefidentyfikator URI danych.
  2. Przykład pobierania kotwicy . Używa <a href="your-data-uri" download="filename.txt">do określenia nazwy pliku.
Viacheslav Dobromyslov
źródło
3
przykład płótna prowadzi do 404
Karel Bílek
Atrybut pobierania działa dla mnie w przypadku adresu URL danych PDF w przeglądarce Chrome i mobilnym safari.
bbsimonbb
7

Łącząc odpowiedzi z @owencm i @ Chazt3n, ta funkcja pozwoli na pobranie tekstu z IE11, Firefoxa i Chrome. (Przepraszamy, nie mam dostępu do Safari ani Opery, ale jeśli spróbujesz i zadziała, dodaj komentarz).

initiate_user_download = function(file_name, mime_type, text) {
    // Anything but IE works here
    if (undefined === window.navigator.msSaveOrOpenBlob) {
        var e = document.createElement('a');
        var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
        e.setAttribute('href', href);
        e.setAttribute('download', file_name);
        document.body.appendChild(e);
        e.click();
        document.body.removeChild(e);
    }
    // IE-specific code
    else {
        var charCodeArr = new Array(text.length);
        for (var i = 0; i < text.length; ++i) {
            var charCode = text.charCodeAt(i);
            charCodeArr[i] = charCode;
        }
        var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
        window.navigator.msSaveOrOpenBlob(blob, file_name);
    }
}

// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');
kevinarpe
źródło
1

Dla każdego, kto ma problemy z IE:

Proszę, zagłosuj za odpowiedzią Yetti: zapisywanie kanwy lokalnie w IE

dataURItoBlob = function(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");
Chazt3n
źródło
0

Twój problem zasadniczo sprowadza się do stwierdzenia, że ​​„nie wszystkie przeglądarki to obsługują”.

Możesz wypróbować obejście i udostępnić rozpakowane pliki z obiektu Flash, ale wtedy stracisz czystość samego JS (w każdym razie nie jestem pewien, czy możesz obecnie „przeciągać pliki do przeglądarki” bez jakiegoś rozwiązania Flash - czy to może funkcja HTML5?)

Piskvor opuścił budynek
źródło