Если, например, вы перейдете по ссылке:
data:application/octet-stream;base64,SGVsbG8=
Браузер предложит вам загрузить файл, состоящий из данных, содержащихся как base64 в самой гиперссылке. Есть ли способ предложить в разметке имя по умолчанию? Если нет, то есть ли решение на JavaScript?
Некоторые браузеры поддерживают необязательный параметр "name" для медиатипа: data:application/pdf;name=document.pdf;base64,BASE64_DATA_ENCODED.
У меня была проблема с Firefox pdf.js, который в некоторых случаях имеет тенденцию зависать, если не может извлечь имя файла из uri данных. см. stackoverflow.com/questions/45585921/…
@mems Какие браузеры поддерживают параметр name? Не могли бы вы указать мне на какую-нибудь справочную документацию? (мой гугл-фу меня подвел).
@DimuDesigns Хотя бы Firefox в то время. Похоже, что это уже не так. Это связано с параметром «имя» MIME Content-Type (! = Content-Disposition) (не в RFC?)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Согласно RFC 2397, нет, нет.
Также, похоже, нет никакого атрибут элемента <a>, который вы могли бы использовать.
Однако HTML5 впоследствии представил атрибут download в элементе <a>, хотя на момент написания поддержка не была универсальной (например, поддержка MSIE отсутствует)
второе предложение было правильным на момент написания, но больше нет. Однако на данный момент он еще не получил широкого распространения.
см. этот комментарий для получения дополнительной информации :)
@flyingsheep, Это является широко внедрено.
это было не 3 года назад, когда я написал этот комментарий
Если файл такой длинный, загрузка не удалась.
Если кому-то интересно о поддержке, здесь - это страница caniuse для этой функции.
Нет.
Вся цель в том, что это поток данных, а не файл. Источник данных не должен знать, что пользовательский агент обрабатывает его как файл ... а это не так.
Целью data: является подделка блока данных внутренний в формат URL без необходимости читать его из источника на основе протокола. Ссылка в ответе @ilex показывает, что возможность предложить предпочтительное имя для написать считается полезной, даже если она еще не реализована.
@Alnitak: Полезно? Абсолютно. Технически приемлемо? Все еще не убежден. :)
@Tomalak учитывает разницу между загрузкой данных и их сохранением - просто потому, что blob закодирован в строке data: URL не означает, что у него не должно быть предпочтительного имени для его сохранения.
@Alnitak: Сами данные не должны знать, как вы загружаете или же, сохраните их. Это данные.
Но ваша фраза о том, что это «вся цель», неверна. data: был специально изобретен, чтобы позволить (небольшому) контенту в соответствии отображаться в формате URL-адресов, собранных вместе, чтобы он мог использоваться такими вещами, как теги изображений, без отдельного HTTP-запроса. HTML говорит, что содержимое атрибута img src должно быть URL-адресом, что и было создано в RFC 2397. Нет никакого «источника данных».
@Alnitak: Совершенно верно. Нет источника данных. Нет контекста. URI является данных.
@LightnessRacesinOrbit Сохранение пустого файла с URI в качестве имени файла имело бы смысл, верно? Кстати, у нас есть URL.createObjectURL, чтобы усугубить ситуацию.
@ LoïcFaure-Lacroix: Да, если вам нужно имя файла. В противном случае лучше всего сохранить HTTP-запрос.
Это своего рода хакерство, но я был в такой же ситуации раньше. Я динамически генерировал текстовый файл в javascript и хотел предоставить его для загрузки, закодировав его с помощью data-URI.
Это возможно при серьезном вмешательстве пользователя незначительный. Сгенерируйте ссылку <a href = "data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. Как я уже сказал, это неэлегантно, но работает, если вам не нужно профессиональное решение.
Это можно сделать менее болезненным, если сначала скопировать имя в буфер обмена с помощью flash. Конечно, если вы позволите себе использовать Flash или Java (теперь, я думаю, со все меньшей и меньшей поддержкой браузеров?), Вы, вероятно, могли бы найти другой способ сделать это.
Это не решение и не соответствует тому, о чем просили. Извиняюсь.
Lol @ "незначительное вмешательство пользователя". Заставить пользователя сделать все за вас - это не «незначительное вмешательство пользователя».
Объедините это с stackoverflow.com/questions/17311645/…, чтобы активировать сгенерированную ссылку, и вам не потребуется вмешательство пользователя. Вы можете указать Атрибут HTML5 download, чтобы предложить имя, указанное в многоДругиеответы.
Это отличный способ обхода Safari. Используйте Modernizr, чтобы определить, когда атрибут загрузки не поддерживается, и обновите текст ссылки!
Взгляните на эту ссылку: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html
Цитировать:
It even works (as in, doesn't cause a problem) with ;base64 at the end
like this (in Opera at least):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
Также есть информация в остальных сообщениях обсуждения.
к сожалению, это не загружается.
это обсуждение касалось расширения предложенный для формата URI данных - оно не было реализовано.
Реализовано или нет, но с существующей поддержкой произвольных параметров это было бы здорово.
Я немного искал источники 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
Здорово! Хотя я не обязательно согласен с тем, что Firefox является высшим авторитетом в отношении того, что существует. :)
Используйте атрибут download:
<a download='FileName' href='your_url'>
Атрибут download работает на Chrome, Firefox, Edge, Opera, настольный Safari 10+, iOS Safari 13+, но не IE11.
Это единственный полный ответ. Нет, вы не можете этого сделать с data: URI. Да, вы можете указать имя файла для ссылки для загрузки с помощью чистого Javascript. Спасибо!
@BioDesign: он работает даже с данными: URI в хроме. См .: jsfiddle.net/pYpqW
но вы не можете сделать это с window.location.replace. если вы, например, хотите создать данные: uri или один, сгенерированный window.URL.createObjectURL, и загрузить его как файл, вам нужно будет создать <a> и щелкнуть по нему: jsfiddle.net/flyingsheep/wpQtH (нет, $(...).click() не работает)
Это функция WHATWG, которую реализует Google, но поскольку это (неофициальный) стандарт, он может стать популярным. whatwg.org/specs/web-apps/current-work/multipage/…
Только если бы весь браузер был похож на Chrome ... [вздох]
@flyingsheep $('<a href = "data:text/plain,Test" download = "test.txt">')[0].click(), похоже, здесь отлично работает (Chrome 23) (примечание: я использовал собственный метод click, а не jQuery). Демо: jsfiddle.net/2zsRW
но в firefox работает только jsfiddle.net/2zsRW/1. может быть, какая-то политика или ошибка одного и того же происхождения? (в сторону: поскольку атрибут загрузки еще не реализован, он просто заменяет фрейм вместо загрузки)
@flyingsheep, похоже, они применяют политику одного и того же происхождения в Firefox. «В Firefox 20 этот атрибут учитывается только для ссылок на ресурсы с одинаковым происхождением». developer.mozilla.org/en-US/docs/Web/HTML/Element/a В моем тестировании Chrome не имеет этого ограничения.
@Pacerier, спасибо, что обновляете ответ, но когда это срок "в настоящее время"
@jcolebrand, это по дате редактирования, которую можно увидеть под постом. Кстати, где комментарий, в котором ты назвал меня придурком?
Проблема с этим решением заключается в том, что файл воля загружается, если пользователь щелкает ссылку. Что, если вы просто хотите указать имя файла, если пользователь щелкнет правой кнопкой мыши + Сохранить ссылку как ...?
Почему это не один из самых популярных ответов?
@streetlight 8 лет спустя, и Chrome заблокировал все URL-адреса данных верхнего кадра по соображениям безопасности. Таков цикл технологических компаний.
В Google Code есть крошечный сценарий обходного пути, который сработал для меня:
http://code.google.com/p/download-data-uri/
Он добавляет форму с данными в ней, отправляет ее, а затем снова удаляет форму. Хакерский, но он сработал за меня. Требуется jQuery.
Эта ветка появилась в Google перед страницей Google Code, и я подумал, что было бы полезно разместить здесь ссылку.
Интересный сценарий, но он требует, чтобы сервер получил ответ и правильно отправил его? jsfiddle.net/hZySf
Я не уверен, откуда генерируется файл ... этот файл хранится в кодировке base64? (Я не слишком знаком с base64)
@streetlight: «Файл» (т.е. данные) генерируется Javascript. Контекст этого проекта (и, вероятно, большей части здесь) предполагает, что у вас есть способ получить желаемые данные в переменной JS. Разница в том, что вместо того, чтобы представлять его пользователю через URI data:..., этот скрипт создает форму для POST его на сервер. И затем сервер предположительно повторяет его прямо как ответ HTTP «загрузить» (то есть с соответствующим заголовком Content-Disposition, указывающим имя файла).
вы можете добавить атрибут загрузки к элементу привязки.
образец:
<a download = "abcd.cer"
href = "data:application/stream;base64,MIIDhTC......">down</a>
Следующий фрагмент кода 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")
Это не работает в Firefox, я добавил расширенный ответ ниже с совместимостью с Fx.
В наши дни Chrome делает это очень просто:
function saveContent(fileContents, fileName)
{
var link = document.createElement('a');
link.download = fileName;
link.href = 'data:,' + fileContents;
link.click();
}
Я знаю, что все эти другие ответы говорят об этом, сработало с первой попытки в Chrome 30.
Сейчас это происходит, но это не всегда было так просто. Многие из этих ответов были получены много лет назад. И они также работают для других браузеров.
Обратитесь к http://caniuse.com/#feat=download для получения полного списка совместимых браузеров.
@tixastronauta: Несмотря на информацию на этой странице, не работает в моем firefox 44. Хорошо работает в Chrome. 48
Привет, @Holf, есть ли способ добавить тип или расширение файла или его так же просто, как указать его как имя файла?
есть способ получше, потому что с его помощью вы не можете сохранить текстовый файл, разделенный на абзацы. мой вариант: 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(); я нашел ответ здесь
К сожалению, это тот же предел в 2 МБ в Chrome при использовании с URL-адресом данных: stackoverflow.com/a/41755526/1024735
Вот версия 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();
С jQuery 1.11 я получаю исключение из-за .remove (). Я обошел это, назначив $().appendTo() переменной, а затем вызвав variable.click(); variable.remove()
@ p0lar_bear вы должны получить это исключение с любым jQuery, потому что получение [0] из любого «элемента jQuery» должно возвращать первый элемент DOM, который он представляет, что по существу «выводит вас из» jQuery.
На самом деле вам вообще не нужно добавлять / удалять элемент - см. Комментарии на stackoverflow.com/a/17311705/1037948
Только 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) загрузит файл с именем по умолчанию или они просто покажут это в новой вкладке, если это поддерживаемый тип файла: изображения, видео, аудиофайлы,…
Обе демонстрации у меня отлично работают в Chrome 38 (но они должны работать в Chrome 14+).
У меня это работает, но после этого страница браузера обновляется. Хотите знать, как этого избежать?
Не работает в Chrome для размера файла> 2 МБ из-за ограничения Chrome stackoverflow.com/questions/695151/…
Предел относится к URI data:, о чем упоминается в вопросе. Этот ответ также работает с Blobs и всем, что имеет URI
Работал как шарм. Успешно справился.
Используя работники сферы обслуживания, это наконец возможно в прямом смысле слова.
<a href, <img src, window.open (url), абсолютно все, что можно сделать с «настоящим» URL.Теперь браузер предложит 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 );
}
});
Интересно! Однако пока поддержка кажется довольно мелкой: caniuse.com/#feat=serviceworkers
Есть ли способ "ответить" другим прямым URL-адресом файла?
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var sessionId ='\n';
var token = '\n';
var caseId = CaseIDNumber + '\n';
var url = casewebUrl+'\n';
var uri = sessionId + token + caseId + url;//data in file
var fileName = "file.i4cvf";// any file name with any extension
if (isIE)
{
var fileData = ['\ufeff' + uri];
var blobObject = new Blob(fileData);
window.navigator.msSaveOrOpenBlob(blobObject, fileName);
}
else //chrome
{
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
fs.root.getFile(fileName, { create: true }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
var fileData = ['\ufeff' + uri];
var blob = new Blob(fileData);
fileWriter.addEventListener("writeend", function () {
var fileUrl = fileEntry.toURL();
var link = document.createElement('a');
link.href = fileUrl;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}, false);
fileWriter.write(blob);
}, function () { });
}, function () { });
}, function () { });
}
пожалуйста, добавьте к своему ответу более подробное объяснение - stackoverflow.com/help/how-to-answer
этот ответ - мусор
Этот работает с 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 для загрузки. Уловка состоит в том, чтобы использовать Файл вместо Blob.
Вы действительно можете добиться этого в Chrome и FireFox.
Попробуйте следующий URL-адрес, он загрузит использованный код.
data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==
<a href=.. download=.. > работает для щелчка левой и правой кнопкой мыши -> сохранить ссылку как ..,
но <img src=.. download=.. > не работает при щелчке правой кнопкой мыши -> сохранить изображение как .., предлагается "Download.jped".
Если объединить оба: <a href=.. download=..><img src=..></a>
он работает для щелчка левой кнопкой мыши, щелчка правой кнопкой мыши -> сохранить ссылку как .., щелчок правой кнопкой мыши -> сохранить изображение как ..
Вам нужно написать data-uri дважды (href и src), поэтому для больших файлов изображений лучше скопировать uri с помощью javascript.
протестировано с Chrome / Edge 88
возможно, не имеет отношения к этой проблеме, но я предлагаю использовать blob & URL.createObjectURL, если это не сервер или препятствие старого браузера