Браузер / HTML Примусове завантаження зображення із src = “data: image / jpeg; base64…”


85

Я генерую зображення на стороні клієнта і відображаю його у форматі HTML таким чином:

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

Я хочу запропонувати можливість завантажити сформоване зображення.

Як я можу зрозуміти, що браузер відкриває діалог збереження файлу (або просто завантажує зображення, як chrome або firefox у папку для завантаження), що дозволяє користувачеві зберігати зображення, не натискаючи правою кнопкою миші та зберігаючи як на зображенні?

Я вважаю за краще рішення без взаємодії з сервером. Тому я усвідомлюю, що це було б можливо, якби я спочатку завантажив Зображення, а потім розпочав завантаження.

Дуже дякую!

Відповіді:


119

Просто замініть image/jpegна application/octet-stream. Клієнт не розпізнає URL-адресу як вбудований ресурс і запитує діалогове вікно завантаження.

Простим рішенням для JavaScript буде:

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

Іншим методом є використання 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!
};

Відповідна документація


1
чомусь він здається зламаним в Chrome 19.0 beta, але він працює на Chrome 18 і Firefox, тому я в порядку. Чи є можливість встановити ім'я файлу?
alex

Неможливо встановити ім'я файлу в URI даних. Навіть коли для експорту даних використовується полотно / Blob , ім'я файлу встановити неможливо. Я додав до своєї відповіді ще один метод (мабуть, цей буде працювати в Chrome 19).
Роб W

2
Чи вважаєте ви, що перший метод буде застарілим, оскільки він більше не працює в chrome 19?
alex

1
Я не можу знайти відповідного джерела на ньому. До речі, я також знайшов цю відповідь , яка підказує, як встановити ім'я за замовчуванням у Chrome (лише закріплюється, користувач повинен натиснути на нього)
Роб W,

Також знайшов це рішення - схоже, хромоване лише зараз. Дякую за твою підтримку!
alex

97

Ви можете використовувати атрибут завантаження для тегу ...

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

докладніше: https://developer.mozilla.org/en/HTML/element/a#attr-download


1
Як я можу використовувати це рішення, коли динамічно генерую джерело зображення? Я маю на увазі, що у мене є кнопка Завантажити, коли користувач натискає на неї, я роблю деякі обчислення, створюю зображення base64 і ... як я можу змусити завантажувати?
Михайло

У chrome я не можу встановити ім'я файлу за допомогою цього методу. Назва завантаженого файлу залишається "завантажити", незважаючи ні на що. Це трапляється лише при використанні даних: image ...
cmaduro

5
Я знаю, що це стара публікація, але згідно з атрибутом веб-сайту W3Schools 'завантаження' не підтримується IE, Safari та Opera v. <12 w3schools.com/tags/tryit.asp?filename=tryhtml5_a_download2, насправді я спробував це за допомогою IE та це не працює .... :(
Мірко Лугано

6
На момент цього коментаря downloadатрибут все ще не підтримується Safari та IE.
TheCarver

1
у нього є обмеження довжини base64, ви не можете завантажувати більші зображення за допомогою цього схвалення.
Кіран Ченна

15

Я Вгадайте IMG тег потрібен як дитина в вигляді тега, в такий спосіб:

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

або

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

Тільки використовуючи в тег , як пояснено в # 15 не працював для мене з останньою версією Firefox і Chrome, але покласти ті ж дані зображення в обох a.href і img.src теги працював для мене.

З JavaScript це може генеруватися так:

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

справа не в тому, що йому потрібен тег img всередині, у документах MSDN зазначено, що можна використовувати лише вже завантажені ресурси - це повинно працювати, поки у вас є зображення з однаковими даними: base64 де завгодно. msdn.microsoft.com/en-us/library/cc848897.aspx - "З міркувань безпеки URI даних обмежуються завантаженими ресурсами. URI даних не можна використовувати для навігації, сценаріїв, а також для заповнення елементів кадру або iframe."
Dimitar Christoff

5

Погляньте на FileSaver.js . Він надає зручну saveAsфункцію, яка піклується про більшість примх, характерних для браузера.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.