Есть ли способ указать предложенное имя файла при использовании data: URI? - PullRequest
212 голосов
/ 12 ноября 2008

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

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

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

Ответы [ 16 ]

145 голосов
/ 04 августа 2011

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

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

Живой пример на html5-demos.appspot.com /....

В настоящее время работает на Chrome, Firefox, Edge, Opera и настольных Safari, но не на iOS Safari или IE11.

60 голосов
/ 13 мая 2013

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

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}
45 голосов
/ 08 сентября 2014

Только 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 ) загрузят файл со своим именем по умолчанию или просто отобразите его на новой вкладке, если он поддерживает поддерживаемые типы файлов: изображения, видео, аудиофайлы,…


Если вам нужна лучшая совместимость сейчас , используйте Flash-based Downloadify в качестве запасного варианта.

39 голосов
/ 12 ноября 2008

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

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

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

21 голосов
/ 05 июня 2011

Я немного посмотрел на исходники 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

14 голосов
/ 05 апреля 2013

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

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

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

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")
12 голосов
/ 30 мая 2011

номер

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

8 голосов
/ 13 сентября 2012

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

образец:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>
5 голосов
/ 24 января 2015

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

  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 );
    }
});
5 голосов
/ 30 мая 2011

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

Цитата:

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

Данные: текст / обычный; Charset = UTF-8; заголовки = Content-Disposition% 3A% 20attachment% 3B% 20filename% 3D% 22with% 20spaces.txt% 22% 0D% 0AContent-Язык% 3A% 20en; base64,4oiaDQo% 3D

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...