Скачать файл URL данных

127

Я играю с идеей создания полностью основанной на JavaScript утилиты zip / unzip, к которой любой сможет получить доступ из браузера. Они могут просто перетащить свой zip-архив прямо в браузер, и он позволит им загрузить все файлы внутри. Они также могут создавать новые zip-файлы, перетаскивая отдельные файлы внутрь.

Я знаю, что было бы лучше сделать это на стороне сервера, но этот проект просто для развлечения.

Перетаскивание файлов в браузер должно быть достаточно простым, если я воспользуюсь различными доступными методами. (Стиль Gmail)

Мы надеемся, что кодирование / декодирование будет в порядке. Я видел несколько zip-библиотек as3, поэтому уверен, что меня это устроит.

Моя проблема заключается в загрузке файлов в конце.

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

это отлично работает в Firefox, но не в Chrome.

Я могу встроить файлы как изображения в Chrome <img src="data:jpg/image;ba.." />, но файлы не обязательно будут изображениями. Они могут быть любого формата.

Может ли кто-нибудь придумать другое решение или какое-то обходное решение?

Mikee
источник
Текущая поддержка , к сожалению, довольно ограничена
Casebash

Ответы:

42

Идеи:

  • Попробуйте <a href="data:...." target="_blank">(непроверенный)

  • Используйте downloadify вместо URL-адресов данных (также будет работать для IE)

Пекка
источник
@jcubic спасибо, что указали на мертвую ссылку. Новое место загрузки, кажется, github.com/dcneiner/Downloadify
Pekka
Если вы не можете использовать Flash, но используете серверный компонент Java, вы можете использовать это: github.com/suprememoocow/databounce . Он использует сервлет для «отскока» данных от клиента. Было бы довольно легко проделать тот же трюк в других серверных технологиях, таких как Python, ASP.NET и т. Д.
Эндрю Ньюдигейт
Есть ли способ обойтись без вспышки? URL данных для всех браузеров, кроме IE и какой-то ActiveX foo для IE? (Таким образом мне удалось воспроизвести музыку без вспышки: аудио HTML5 для всех браузеров, кроме IE и ActiveX для IE.)
panzi
Downloadify ожидает флеш-плеера в браузере. Если у пользователя нет флеш-плеера, файл не будет загружен
Дживанандан Дж.
187

Если вы также хотите дать файлу предлагаемое имя (вместо значения по умолчанию «загрузка»), вы можете использовать следующее в Chrome, Firefox и некоторых версиях 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;
}

И следующий пример показывает его использование:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");
owencm
источник
6
Вы можете упростить это с помощью link.click()вместо eventFire-функции ... jsfiddle.net/ARTsinn/Ezx5m
yckart
3
Хорошее решение. а что после становится ссылка?
webshaker
6
Переменная link выходит за пределы области видимости в конце функции (обратите внимание, что мы никогда не добавляли ее в dom), поэтому вскоре после этого будет произведена сборка мусора.
owencm
8
Это работает только в Chrome. Если вы хотите, чтобы он работал в Firefox / IE, посмотрите ответ от @MartinoDino.
TrueWill
1
Я пробовал с download.js , как предлагается здесь, и, похоже, он работает. :)
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");

или:

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
источник
событие click на несуществующем элементе: D нет необходимости в appendchild.
Zibri
1
да. вы можете просто вызвать a.click () после того, как вы создали элемент «a», а затем установить href.
user1709076
раньше прямой вызов a.click () не работал, но работал с событием. Теперь они оба работают.
Zibri
1
Это работает в большинстве современных браузеров, но я хотел бы отметить, что добавление к документу с последующим удалением необходимо для поддержки некоторых старых браузеров.
owencm
3
Второе решение следует использовать всякий раз, когда dataUri становится слишком большим (зависит от браузера, но, по моему опыту, Chrome не принимает Uri в несколько мегабайт). См. Также stackoverflow.com/questions/38781968/… .
neural5torm
27

Хочу поделиться своим опытом и помочь кому-то застрять в загрузках, которые не работают в Firefox, и обновил ответ на 2014 год. Приведенный ниже фрагмент будет работать как в firefox, так и в Chrome, и он будет принимать имя файла:

  // 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);
Мартино Дино
источник
4
К сожалению, в Safari это не работает. Safari, похоже, не распознает downloadатрибут. В любом случае, спасибо, сейчас это так близко, насколько я могу.
Мориц Петерсен
это заставляет окно перенаправлять меня на значение href в IE 11. prevetDefault (); не останавливает поведение в IE
b_dubb 01
1
Спасибо, также если btoaне определено (например, в проекте внешнего интерфейса node eslinted) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
Иван Борщов
2
удаление ссылки бессмысленно, она выходит за рамки на следующей строке и будет собрана мусором, это недопустимая цель для удаления.
macdja38 03
1
нет необходимости в document.body.appendChild ... см. мой ответ stackoverflow.com/a/45905238/236062
Zibri
13

Вот чистое решение JavaScript, которое я тестировал при работе в Firefox и Chrome, но не в Internet Explorer:

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

Кроссбраузерные решения, найденные до сих пор:

downloadify -> Требуется Flash

databounce -> Протестировано в IE 10 и 11 и у меня не работает. Требуется сервлет и некоторая настройка. (Неправильно определяет навигатор. Мне пришлось установить IE в режиме совместимости для тестирования, кодировка по умолчанию в сервлете, объект параметров JavaScript с правильным путем к сервлету для абсолютных путей ...) Для браузеров, отличных от IE, он открывает файл в том же окне.

download.js -> http://danml.com/download.html Еще одна похожая, но не проверенная библиотека. Утверждает, что это чистый JavaScript, не требующий сервлета или Flash, но не работает в IE <= 9.

Иисус MC
источник
download.js довольно хорош. Просто проверил IE11, он работает. Большое спасибо!
Рики Цзяо
12

Есть несколько решений, но они зависят от HTML5 и еще не полностью реализованы в некоторых браузерах. Примеры ниже были протестированы в Chrome и Firefox (частично работает).

  1. Пример холста с поддержкой сохранения в файл. Просто установите document.location.hrefURI данных.
  2. Пример загрузки якоря . Используется <a href="your-data-uri" download="filename.txt">для указания имени файла.
Вячеслав Добромыслов
источник
3
пример холста приводит к 404
Карел Билек
Атрибут загрузки работает для меня, для URL-адреса данных PDF в Chrome и мобильного сафари.
bbsimonbb 01
7

Объединяя ответы от @owencm и @ Chazt3n, эта функция позволит загружать текст из IE11, Firefox и Chrome. (Извините, у меня нет доступа к Safari или Opera, но, пожалуйста, добавьте комментарий, если вы попробуете, и это сработает.)

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
источник
1

Для тех, у кого есть проблемы в IE:

Проголосуйте за ответ от Йетти: сохранение холста локально в 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
источник
0

По сути, ваша проблема сводится к тому, что «не все браузеры это поддерживают».

Вы можете попробовать обходной путь и обслуживать распакованные файлы из объекта Flash, но тогда вы потеряете чистоту JS-only (в любом случае, я не уверен, можно ли в настоящее время «перетаскивать файлы в браузер» без какого-либо обходного пути Flash - это может быть функция HTML5?)

Писквор вышел из здания
источник