Есть ли способ указать предлагаемое имя файла при использовании data: URI?

Если, например, вы перейдете по ссылке:

data:application/octet-stream;base64,SGVsbG8=

Браузер предложит вам загрузить файл, состоящий из данных, содержащихся как base64 в самой гиперссылке. Есть ли способ предложить в разметке имя по умолчанию? Если нет, то есть ли решение на JavaScript?


person Community    schedule 12.11.2008    source источник
comment
возможно, не имеет отношения к этой проблеме, но я предлагаю использовать blob & URL.createObjectURL, если это не сервер или старое препятствие браузера   -  person Endless    schedule 20.11.2015
comment
Некоторые браузеры поддерживают необязательное имя параметра медиатипа: data:application/pdf;name=document.pdf;base64,BASE64_DATA_ENCODED   -  person mems    schedule 03.04.2017
comment
У меня была проблема с Firefox pdf.js, который в некоторых случаях имеет тенденцию зависать, если не может извлечь имя файла из uri данных. см. stackoverflow.com/questions/45585921/   -  person Bernhard    schedule 09.08.2017
comment
@mems Какие браузеры поддерживают параметр name? Не могли бы вы указать мне на какую-нибудь справочную документацию? (мой гугл-фу меня подвел).   -  person TheAddonDepot    schedule 25.09.2018
comment
@DimuDesigns Хотя бы Firefox в то время. Похоже, что это уже не так. Это связано с параметром имени MIME Content-Type (! = Content-Disposition) (не в RFC?)   -  person mems    schedule 27.09.2018


Ответы (17)


Используйте атрибут download:

<a download='FileName' href='your_url'>

Атрибут download работает в Chrome, Firefox, Edge, Opera, настольном Safari 10+, iOS Safari 13+ , а не IE11.

person Dan Fabulich    schedule 04.08.2011
comment
Это единственный полный ответ. Нет, вы не можете этого сделать с data: URI. Да, вы можете указать имя файла для ссылки для загрузки с помощью чистого Javascript. Спасибо! - person Biovisualize; 17.11.2011
comment
@BioDesign: он работает даже с данными: URI в хроме. См .: jsfiddle.net/pYpqW - person Senseful; 17.01.2012
comment
но вы не можете сделать это с window.location.replace. если вы, например, хотите создать данные: uri или созданный _2 _ и загрузите его как файл, вам нужно будет создать ‹a› и щелкнуть по нему: jsfiddle. net / flyingsheep / wpQtH (нет, $(...).click() не работает) - person flying sheep; 16.03.2012
comment
Это функция WHATWG, которую реализует Google, но поскольку это (неофициальный) стандарт, он может стать популярным. whatwg.org/specs/ web-apps / current-work / multipage / - person orip; 02.08.2012
comment
Только если бы весь браузер был похож на Chrome ... [вздох] - person streetlight; 14.11.2012
comment
@flyingsheep $('<a href="data:text/plain,Test" download="test.txt">')[0].click(), похоже, здесь отлично работает (Chrome 23) (примечание: я использовал собственный метод click, а не метод jQuery). Демо: jsfiddle.net/2zsRW - person Rob W; 06.12.2012
comment
но в firefox работает только jsfiddle.net/2zsRW/1. может быть, какая-то политика или ошибка одного и того же происхождения? (в стороне: поскольку атрибут загрузки еще не реализован, он просто заменяет фрейм вместо загрузки) - person flying sheep; 06.12.2012
comment
@flyingsheep, похоже, они применяют политику одного и того же происхождения в Firefox. В Firefox 20 этот атрибут учитывается только для ссылок на ресурсы с одинаковым происхождением. developer.mozilla.org/en-US/docs/Web/ HTML / Element / a В моем тестировании Chrome не имеет этого ограничения. - person William Denniss; 19.12.2013
comment
@Pacerier, спасибо, что держите ответ в актуальном состоянии, но когда сейчас срок - person jcolebrand; 03.03.2015
comment
@jcolebrand, это по дате редактирования, которую можно увидеть под постом. Кстати, где комментарий, в котором ты назвал меня придурком? - person Pacerier; 12.03.2015
comment
Проблема с этим решением состоит в том, что файл будет загружен, если пользователь щелкнет ссылку. Что, если вы просто хотите указать имя файла, если пользователь щелкнет правой кнопкой мыши + Сохранить ссылку как ...? - person phn; 31.08.2016
comment
Как это не один из самых популярных ответов? - person FluorescentGreen5; 07.05.2017
comment
@streetlight 8 лет спустя, и Chrome заблокировал все URL-адреса данных верхнего кадра по соображениям безопасности. Таков цикл технологических компаний. - person Seph Reed; 26.11.2020

В наши дни Chrome делает это очень просто:

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}
person Holf    schedule 13.05.2013
comment
Я знаю, что все эти другие ответы говорят об этом, это сработало с первой попытки в Chrome 30. - person Michael J. Calkins; 23.10.2013
comment
Сейчас это происходит, но это не всегда было так просто. Многие из этих ответов были получены много лет назад. И они также работают для других браузеров. - person Holf; 26.10.2013
comment
См. http://caniuse.com/#feat=download для получения полного списка совместимых браузеров. . - person tixastronauta; 13.02.2014
comment
@tixastronauta: Несмотря на информацию на этой странице, не работает в моем firefox 44. Хорошо работает в Chrome. 48 - person Luis A. Florit; 17.02.2016
comment
Привет, @Holf, есть ли способ добавить тип или расширение файла или его так же просто, как указать его как имя файла? - person Fraccier; 31.05.2016
comment
есть способ получше, потому что с его помощью вы не можете сохранить текстовый файл, разделенный на абзацы. мой вариант: var file = new File(rows, "file.csv", {type: 'text/csv'}); var link = document.createElement('a'); link.href = URL.createObjectURL(file); link.download = file.name; link.click(); я нашел ответ здесь - person barbarian; 21.09.2016
comment
К сожалению, это тот же предел в 2 МБ в Chrome при использовании с URL-адресом данных: stackoverflow.com/a/41755526/1024735 - person kevinmicke; 13.12.2018

Только HTML: используйте атрибут download:

<a download="logo.gif" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">Download transparent png</a>


Только Javascript: вы можете сохранить любой URI данных с помощью этого кода:

function saveAs(uri, filename) {
  var link = document.createElement('a');
  if (typeof link.download === 'string') {
    link.href = uri;
    link.download = filename;

    //Firefox requires the link to be in the body
    document.body.appendChild(link);
    
    //simulate click
    link.click();

    //remove the link when done
    document.body.removeChild(link);
  } else {
    window.open(uri);
  }
}

var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
saveAs(file, 'logo.gif');

Chrome, Firefox и Edge 13+ будут использовать указанное имя файла.

IE11, Edge 12 и Safari 9 (которые не поддерживают атрибут download ) загрузят файл со своим именем по умолчанию или просто отобразят его в новой вкладке, если это файл поддерживаемого типа: изображения, видео, аудиофайлы и т. д.

person fregante    schedule 08.09.2014
comment
Обе демонстрации у меня отлично работают в Chrome 38 (но они должны работать в Chrome 14+) - person fregante; 07.10.2014
comment
У меня это работает, но после этого страница браузера обновляется. Хотите знать, как этого избежать? - person ; 18.11.2016
comment
Не работает в Chrome для размера файла ›2 МБ из-за ограничения chrome stackoverflow.com/questions/695151/ - person Pranav Singh; 06.02.2017
comment
Предел относится к data: URI, о чем упоминается в вопросе. Этот ответ также работает с Blobs и всем, что имеет URI - person fregante; 06.02.2017
comment
Работал как шарм. Успешно справился. - person Aarmora; 01.05.2017

Согласно RFC 2397, нет.

Также нет никакого атрибута элемента <a>, который вы могли бы использовать либо.

Однако впоследствии HTML5 представил атрибут download на элемент <a>, хотя на момент написания поддержка не является универсальной (например, нет поддержки MSIE)

person Alnitak    schedule 12.11.2008
comment
второе предложение было правильным на момент написания, но больше не . Однако на данный момент он еще не получил широкого распространения. - person flying sheep; 16.03.2012
comment
см. это комментарий для получения дополнительной информации :) - person flying sheep; 16.03.2012
comment
@flyingsheep, Это широко внедрено. - person Pacerier; 03.03.2015
comment
это было не 3 года назад, когда я написал этот комментарий - person flying sheep; 04.03.2015
comment
Если файл такой длинный, загрузка не удалась. - person deFreitas; 14.10.2016
comment
Если кого-то интересует поддержка, вот страница для этой функции. - person 3ocene; 15.05.2017

Я немного искал источники firefox в netwerk / protocol / data / nsDataHandler.cpp

обработчик данных анализирует только содержимое / тип и кодировку и проверяет, есть ли в строке "; base64"

rfc не определяет имя файла и, по крайней мере, firefox не обрабатывает имя файла для него, код генерирует случайное имя плюс ".part"

Я также проверил журнал Firefox

[b2e140]: DOCSHELL 6e5ae00 InternalLoad data:application/octet-stream;base64,SGVsbG8=
[b2e140]: Found extension '' (filename is '', handling attachment: 0)
[b2e140]: HelperAppService::DoContent: mime 'application/octet-stream', extension ''
[b2e140]: Getting mimeinfo from type 'application/octet-stream' ext ''
[b2e140]: Extension lookup on '' found: 0x0
[b2e140]: Ext. lookup for '' found 0x0
[b2e140]: OS gave back 0x43609a0 - found: 0
[b2e140]: Searched extras (by type), rv 0x80004005
[b2e140]: MIME Info Summary: Type 'application/octet-stream', Primary Ext ''
[b2e140]: Type/Ext lookup found 0x43609a0

интересные файлы, если вы хотите посмотреть исходники Mozilla:

data uri handler: netwerk/protocol/data/nsDataHandler.cpp
where mozilla decides the filename: uriloader/exthandler/nsExternalHelperAppService.cpp
InternalLoad string in the log: docshell/base/nsDocShell.cpp

Думаю, вы можете пока прекратить поиск решения, потому что подозреваю, что его нет :)

как отмечено в этой теме, html5 имеет атрибут download, он также работает в firefox 20 http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-download

person sherpya    schedule 05.06.2011
comment
Прохладный! Хотя я не обязательно согласен с тем, что Firefox является высшим авторитетом в отношении того, что существует. :) - person Gleno; 05.06.2011

Следующий фрагмент Javascript работает в Chrome за счет использования нового атрибута «загрузка» ссылок и имитации щелчка.

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

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

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")
person owencm    schedule 05.04.2013
comment
Это не работает в Firefox, я добавил расширенный ответ ниже с совместимостью с Fx. - person fregante; 08.09.2014

No.

Вся цель в том, чтобы это поток данных, а не файл. Источник данных не должен знать, что пользовательский агент обрабатывает его как файл ... а это не так.

person Lightness Races in Orbit    schedule 30.05.2011
comment
Цель data: - преобразовать блок внутренних данных в формат URL без необходимости чтения его из источника на основе протокола. Ссылка в ответе @ilex показывает, что возможность предложить предпочтительное имя для записи считается полезной, даже если она еще не реализована. - person Alnitak; 05.06.2011
comment
@Alnitak: Полезно? Абсолютно. Технически приемлемо? Все еще не убежден. :) - person Lightness Races in Orbit; 06.06.2011
comment
@Tomalak учитывает разницу между загрузкой данных и их сохранением - просто потому, что blob закодирован в строке data: URL не означает, что у него не должно быть предпочтительного имени для его сохранения. - person Alnitak; 06.06.2011
comment
@Alnitak: Сами данные не должны знать, как вы их загружаете или. Это данные. - person Lightness Races in Orbit; 06.06.2011
comment
Но твоя линия о его цели неверна. data: был специально изобретен, чтобы разрешить (небольшому) встроенному содержимому отображаться в формате URL-адресов, собранных вместе, чтобы его можно было использовать такими вещами, как теги изображений, без отдельного HTTP-запроса. HTML говорит, что содержимое атрибута img src должно быть URL-адресом, что и было создано в RFC 2397. Нет источника данных. - person Alnitak; 06.06.2011
comment
@Alnitak: Совершенно верно. Нет источника данных. Нет контекста. URI - это данные. - person Lightness Races in Orbit; 06.06.2011
comment
@LightnessRacesinOrbit Сохранение пустого файла с URI в качестве имени файла имело бы смысл, верно? Кстати, у нас есть URL.createObjectURL, чтобы еще больше усугубить ситуацию. - person Loïc Faure-Lacroix; 24.02.2017
comment
@ LoïcFaure-Lacroix: Да, если вам нужно имя файла. В противном случае лучше всего сохранить HTTP-запрос. - person Lightness Races in Orbit; 24.02.2017

вы можете добавить атрибут загрузки к элементу привязки.

образец:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>
person cuixiping    schedule 13.09.2012

Используя сервис-воркеров, это наконец-то возможно в самом истинном смысл.

  1. Создайте поддельный URL-адрес. Например, /saveAs/myPrettyName.jpg.
  2. Используйте URL в <a href, <img src, window.open (url), абсолютно все, что можно сделать с "настоящим" URL.
  3. Внутри воркера перехватите событие выборки и ответьте правильными данными.

Теперь браузер предложит myPrettyName.jpg, даже если пользователь откроет файл в новой вкладке и попытается сохранить его там. Это будет точно так, как если бы файл пришел с сервера.

// In the service worker
self.addEventListener( 'fetch', function(e)
{
    if( e.request.url.startsWith( '/blobUri/' ) )
    {
        // Logic to select correct dataUri, and return it as a Response
        e.respondWith( dataURLAsRequest );
    }
});
person Adria    schedule 24.01.2015
comment
Интересно! Однако на данный момент поддержка кажется довольно мелкой: caniuse.com/#feat=serviceworkers - person tuomassalo; 06.02.2015
comment
Есть ли способ ответить другим прямым URL-адресом файла? - person Iulian Onofrei; 10.02.2016

Посмотрите на эту ссылку: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

Цитировать:

Он даже работает (например, не вызывает проблем) с; base64 в конце
вот так (по крайней мере, в Opera):

data: text / plain; charset = utf-8; headers = Content-Disposition% 3A% 20attachment% 3B% 20filename% 3D% 22with% 20spaces.txt% 22% 0D% 0AContent-Language% 3A% 20en; base64 , 4oiaDQo% 3D

Также есть информация в остальных сообщениях обсуждения.

person silex    schedule 30.05.2011
comment
к сожалению, это не скачивается. - person James Khoury; 30.05.2011
comment
это обсуждение касалось предлагаемого расширения формата URI данных - оно не было реализовано. - person Alnitak; 30.05.2011
comment
Реализовано или нет, но при существующей поддержке произвольных параметров это было бы здорово. - person Dan Lugg; 21.12.2012

В Google Code есть крошечный сценарий обходного пути, который у меня сработал:

http://code.google.com/p/download-data-uri/

Он добавляет форму с данными в ней, отправляет ее, а затем снова удаляет форму. Хакерский, но он сработал за меня. Требуется jQuery.

Эта ветка появилась в Google перед страницей Google Code, и я подумал, что было бы полезно разместить здесь ссылку.

person Fabian B.    schedule 11.01.2012
comment
Я не уверен, откуда генерируется файл ... этот файл хранится в кодировке base64? (Я не слишком знаком с base64) - person streetlight; 14.11.2012
comment
@streetlight: файл (т.е. данные) генерируется Javascript. Контекст этого проекта (и, вероятно, большей части здесь) предполагает, что у вас есть способ получить желаемые данные в переменной JS. Разница в том, что вместо того, чтобы представлять его пользователю через data:... URI, этот сценарий создает форму для POST его на сервер. И затем сервер предположительно повторяет его прямо как ответ загрузки HTTP (то есть с соответствующим заголовком Content-Disposition, указывающим имя файла). - person Andrzej Doyle; 14.01.2013

Вот версия jQuery, основанная на версии Холфа и работающая с Chrome и Firefox, тогда как его версия, похоже, работает только с Chrome. Немного странно добавлять что-то в тело для этого, но если у кого-то есть вариант получше, я за него.

var exportFileName = "export-" + filename;
$('<a></a>', {
    "download": exportFileName,
    "href": "data:," + JSON.stringify(exportData, null,5),
    "id": "exportDataID"
}).appendTo("body")[0].click().remove();
person kgividen    schedule 20.02.2014
comment
С jQuery 1.11 я получаю исключение из-за .remove (). Я обошел это, присвоив переменной $().appendTo() и вызвав variable.click(); variable.remove() - person p0lar_bear; 04.03.2014
comment
@ p0lar_bear вы должны получить это исключение с любым jQuery, потому что получение [0] из любого элемента jQuery должно возвращать первый элемент DOM, который он представляет, что по существу выводит вас из jQuery. - person drzaus; 11.12.2014
comment
На самом деле вам вообще не нужно добавлять / удалять элемент - см. Комментарии на странице stackoverflow.com/a/17311705/1037948 - person drzaus; 11.12.2014

Это своего рода хакерство, но я и раньше был в такой же ситуации. Я динамически генерировал текстовый файл в javascript и хотел предоставить его для загрузки, закодировав его с помощью data-URI.

Это возможно при незначительном серьезном вмешательстве пользователя. Создайте ссылку <a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. Как я уже сказал, это неэлегантно, но работает, если вам не нужно профессиональное решение.

Это можно сделать менее болезненным, если сначала скопировать имя в буфер обмена с помощью flash. Конечно, если вы позволите себе использовать Flash или Java (теперь, я думаю, со все меньшей и меньшей поддержкой браузеров?), Вы, вероятно, могли бы найти другой способ сделать это.

person ninjagecko    schedule 30.05.2011
comment
Это не решение и не соответствует тому, о чем просили. Извините. - person jcolebrand; 06.06.2011
comment
Lol @ незначительное вмешательство пользователя. Заставить пользователя сделать все за вас - это не второстепенное вмешательство пользователя. - person Lightness Races in Orbit; 07.06.2011
comment
Объедините это с stackoverflow.com/questions/17311645/, чтобы активируйте сгенерированную ссылку, и вам не потребуется вмешательство пользователя. Вы можете указать атрибут HTML5 download, чтобы предложить имя, указанное многие другое answers. - person drzaus; 02.07.2014
comment
Это отличный способ обхода Safari. Используйте Modernizr, чтобы определить, когда атрибут загрузки не поддерживается, и обновите текст ссылки! - person littledynamo; 01.06.2016

Этот работает с Firefox 43.0 (более старый не тестировался):

dl.js:

function download() {
  var msg="Hello world!";
  var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});

  var a = document.createElement("a");
  a.href = URL.createObjectURL(blob);

  window.location.href=a;
}

dl.html

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8"/>
    <title>Test</title>
    <script type="text/javascript" src="dl.js"></script>
</head>

<body>
<button id="create" type="button" onclick="download();">Download</button>
</body>
</html>

Если нажать кнопку, будет предложен файл с именем hello.bin для загрузки. Уловка состоит в том, чтобы использовать File вместо Blob.

ссылка: https://developer.mozilla.org/de/docs/Web/API/File

person NeutronenStern    schedule 02.01.2016

<a href=.. download=.. > работает для щелчка левой и правой кнопкой мыши - ›сохранить ссылку как ..,

но <img src=.. download=.. > не работает при щелчке правой кнопкой мыши - ›сохранить изображение как .., рекомендуется Download.jped.

Если объединить оба: <a href=.. download=..><img src=..></a>

он работает для щелчка левой кнопкой мыши, щелчка правой кнопкой мыши - ›сохранить ссылку как .., щелчок правой кнопкой мыши -› сохранить изображение как ..

Вам нужно написать data-uri дважды (href и src), поэтому для больших файлов изображений лучше скопировать uri с помощью javascript.

протестировано с Chrome / Edge 88

person Micha    schedule 11.02.2021

Вы действительно можете добиться этого в Chrome и FireFox.

Попробуйте следующий URL-адрес, он загрузит использованный код.

data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==
person Chad Scira    schedule 26.11.2016

person    schedule
comment
пожалуйста, добавьте более подробное объяснение к своему ответу - stackoverflow.com/help/how-to-answer - person Sebastian Brosch; 25.11.2015
comment
этот ответ - мусор - person Jonathan Taylor; 20.07.2017