Browser / HTML Download des Bildes von src erzwingen = "data: image / jpeg; base64…"

85

Ich generiere ein Bild auf der Clientseite und zeige es mit HTML wie folgt an:

<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgM...."/>

Ich möchte die Möglichkeit bieten, das generierte Bild herunterzuladen.

Wie kann ich feststellen, dass der Browser eine Datei zum Speichern von Dialogen öffnet (oder das Bild einfach wie Chrome oder Firefox in den Download-Ordner herunterlädt), mit der der Benutzer das Bild speichern kann, ohne mit der rechten Maustaste klicken und es wie auf dem Bild speichern zu müssen?

Ich würde eine Lösung ohne Serverinteraktion bevorzugen. Ich bin mir also bewusst, dass es möglich wäre, wenn ich zuerst das Bild hochlade und dann den Download starte.

Vielen Dank!

Alex
quelle

Antworten:

118

Ersetzen Sie einfach image/jpegmit application/octet-stream. Der Client erkennt die URL nicht als Inline-fähige Ressource und fordert einen Download-Dialog auf.

Eine einfache JavaScript-Lösung wäre:

//var img = reference to image
var url = img.src.replace(/^data:image\/[^;]+/, 'data:application/octet-stream');
window.open(url);
// Or perhaps: location.href = url;
// Or even setting the location of an <iframe> element, 

Eine andere Methode ist die Verwendung eines blob:URI:

var img = document.images[0];
img.onclick = function() {
    // atob to base64_decode the data-URI
    var image_data = atob(img.src.split(',')[1]);
    // Use typed arrays to convert the binary data to a Blob
    var arraybuffer = new ArrayBuffer(image_data.length);
    var view = new Uint8Array(arraybuffer);
    for (var i=0; i<image_data.length; i++) {
        view[i] = image_data.charCodeAt(i) & 0xff;
    }
    try {
        // This is the recommended method:
        var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
    } catch (e) {
        // The BlobBuilder API has been deprecated in favour of Blob, but older
        // browsers don't know about the Blob constructor
        // IE10 also supports BlobBuilder, but since the `Blob` constructor
        //  also works, there's no need to add `MSBlobBuilder`.
        var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder);
        bb.append(arraybuffer);
        var blob = bb.getBlob('application/octet-stream'); // <-- Here's the Blob
    }

    // Use the URL object to create a temporary URL
    var url = (window.webkitURL || window.URL).createObjectURL(blob);
    location.href = url; // <-- Download!
};

Relevante Dokumentation

Rob W.
quelle
1
Aus irgendeinem Grund scheint es in Chrome 19.0 Beta kaputt zu sein, aber es funktioniert auf Chrome 18 und Firefox, also geht es mir gut. Gibt es eine Möglichkeit, einen Dateinamen festzulegen?
alex
Es gibt keine Möglichkeit, den Dateinamen in einem Daten-URI festzulegen. Selbst wenn ein Canvas / Blob zum Exportieren der Daten verwendet wird, kann der Dateiname nicht festgelegt werden. Ich habe meiner Antwort eine andere Methode hinzugefügt (ich denke, dass diese in Chrome 19 funktioniert).
Rob W
2
Denken Sie, dass die erste Methode veraltet sein wird, weil sie in Chrome 19 nicht mehr funktioniert?
Alex
1
Ich kann keine relevante Quelle finden. Ich habe übrigens auch diese Antwort gefunden , die vorschlägt, wie man einen Standardnamen in Chrome
Rob W
Auch diese Lösungen gefunden - scheint erstmal Chrom zu sein. Danke für deine Unterstützung!
Alex
96

Sie können das Download-Attribut für ein Tag verwenden ...

<a href="data:image/jpeg;base64,/9j/4AAQSkZ..." download="filename.jpg"></a>

Weitere Informationen : https://developer.mozilla.org/en/HTML/element/a#attr-download

Bruce Aldridge
quelle
1
Wie kann ich diese Lösung verwenden, wenn ich die Bildquelle dynamisch generiere? Ich meine, ich habe die Schaltfläche Herunterladen. Wenn der Benutzer darauf klickt, führe ich einige Berechnungen durch, generiere ein base64-Image und ... wie kann ich das Herunterladen erzwingen?
Mikhail
In Chrome kann ich den Dateinamen mit dieser Methode nicht festlegen. Der Name der heruntergeladenen Datei bleibt "download", egal was passiert. Dies geschieht nur bei Verwendung von Daten: Bild ...
cmaduro
5
Ich weiß, dass dies ein alter Beitrag ist, aber laut W3Schools-Website wird das Download-Attribut von IE, Safari und Opera v. <12 w3schools.com/tags/tryit.asp?filename=tryhtml5_a_download2 nicht unterstützt. Tatsächlich habe ich es mit IE und versucht es funktioniert nicht .... :(
Mirko Lugano
6
Zum Zeitpunkt dieses Kommentars wird das downloadAttribut Safari und IE noch nicht unterstützt.
TheCarver
1
Es gibt eine Längenbeschränkung von base64. Mit diesem Ansatz können Sie keine größeren Bilder herunterladen.
Kiran Chenna
15

Ich denke, ein img- Tag wird als Kind eines Tags auf folgende Weise benötigt:

<a download="YourFileName.jpeg" href="data:image/jpeg;base64,iVBO...CYII=">
    <img src="data:image/jpeg;base64,iVBO...CYII="></img>
</a>

oder

<a download="YourFileName.jpeg" href="/path/to/OtherFile.jpg">
    <img src="/path/to/OtherFile.jpg"></img>
</a>

Nur die Verwendung eines in # 15 erläuterten a- Tags funktionierte bei der neuesten Version von Firefox und Chrome nicht, aber das Einfügen der gleichen Bilddaten in a.href- und img.src- Tags funktionierte bei mir.

Aus JavaScript könnte es folgendermaßen generiert werden:

var data = canvas.toDataURL("image/jpeg");

var img = document.createElement('img');
img.src = data;

var a = document.createElement('a');
a.setAttribute("download", "YourFileName.jpeg");
a.setAttribute("href", data);
a.appendChild(img);

var w = open();
w.document.title = 'Export Image';
w.document.body.innerHTML = 'Left-click on the image to save it.';
w.document.body.appendChild(a);
user3521208
quelle
Es ist nicht so, dass ein IMG-Tag erforderlich ist. In den MSDN-Dokumenten wird angegeben, dass nur bereits heruntergeladene Ressourcen verwendet werden können. Dies sollte funktionieren, solange Sie das Image mit denselben Daten haben: base64 überall. msdn.microsoft.com/en-us/library/cc848897.aspx - "Aus Sicherheitsgründen sind Daten-URIs auf heruntergeladene Ressourcen beschränkt. Daten-URIs können nicht zur Navigation, zum Erstellen von Skripten oder zum Auffüllen von Frame- oder Iframe-Elementen verwendet werden."
Dimitar Christoff
5

Schauen Sie sich FileSaver.js an . Es bietet eine praktische saveAsFunktion, die sich um die meisten browserspezifischen Macken kümmert.

Jesus
quelle