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

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

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

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

возможно, не имеет отношения к этой проблеме, но я предлагаю использовать blob & URL.createObjectURL, если это не сервер или препятствие старого браузера

Endless 20.11.2015 23:48

Некоторые браузеры поддерживают необязательный параметр "name" для медиатипа: data:application/pdf;name=document.pdf;base64,BASE64_DATA_EN‌​CODED.

mems 03.04.2017 16:24

У меня была проблема с Firefox pdf.js, который в некоторых случаях имеет тенденцию зависать, если не может извлечь имя файла из uri данных. см. stackoverflow.com/questions/45585921/…

Bernhard 09.08.2017 11:56

@mems Какие браузеры поддерживают параметр name? Не могли бы вы указать мне на какую-нибудь справочную документацию? (мой гугл-фу меня подвел).

TheAddonDepot 25.09.2018 04:46

@DimuDesigns Хотя бы Firefox в то время. Похоже, что это уже не так. Это связано с параметром «имя» MIME Content-Type (! = Content-Disposition) (не в RFC?)

mems 27.09.2018 17:29
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
234
5
178 270
17

Ответы 17

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

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

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

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

flying sheep 16.03.2012 21:48

см. этот комментарий для получения дополнительной информации :)

flying sheep 16.03.2012 22:44

@flyingsheep, Это является широко внедрено.

Pacerier 03.03.2015 19:04

это было не 3 года назад, когда я написал этот комментарий

flying sheep 04.03.2015 01:20

Если файл такой длинный, загрузка не удалась.

deFreitas 14.10.2016 19:49

Если кому-то интересно о поддержке, здесь - это страница caniuse для этой функции.

3ocene 15.05.2017 22:24

Нет.

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

Целью data: является подделка блока данных внутренний в формат URL без необходимости читать его из источника на основе протокола. Ссылка в ответе @ilex показывает, что возможность предложить предпочтительное имя для написать считается полезной, даже если она еще не реализована.

Alnitak 05.06.2011 13:27

@Alnitak: Полезно? Абсолютно. Технически приемлемо? Все еще не убежден. :)

Lightness Races in Orbit 06.06.2011 00:21

@Tomalak учитывает разницу между загрузкой данных и их сохранением - просто потому, что blob закодирован в строке data: URL не означает, что у него не должно быть предпочтительного имени для его сохранения.

Alnitak 06.06.2011 00:26

@Alnitak: Сами данные не должны знать, как вы загружаете или же, сохраните их. Это данные.

Lightness Races in Orbit 06.06.2011 00:44

Но ваша фраза о том, что это «вся цель», неверна. data: был специально изобретен, чтобы позволить (небольшому) контенту в соответствии отображаться в формате URL-адресов, собранных вместе, чтобы он мог использоваться такими вещами, как теги изображений, без отдельного HTTP-запроса. HTML говорит, что содержимое атрибута img src должно быть URL-адресом, что и было создано в RFC 2397. Нет никакого «источника данных».

Alnitak 06.06.2011 02:14

@Alnitak: Совершенно верно. Нет источника данных. Нет контекста. URI является данных.

Lightness Races in Orbit 06.06.2011 02:22

@LightnessRacesinOrbit Сохранение пустого файла с URI в качестве имени файла имело бы смысл, верно? Кстати, у нас есть URL.createObjectURL, чтобы усугубить ситуацию.

Loïc Faure-Lacroix 24.02.2017 16:08

@ LoïcFaure-Lacroix: Да, если вам нужно имя файла. В противном случае лучше всего сохранить HTTP-запрос.

Lightness Races in Orbit 24.02.2017 17:18

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

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

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

Это не решение и не соответствует тому, о чем просили. Извиняюсь.

jcolebrand 06.06.2011 01:38

Lol @ "незначительное вмешательство пользователя". Заставить пользователя сделать все за вас - это не «незначительное вмешательство пользователя».

Lightness Races in Orbit 07.06.2011 00:28

Объедините это с stackoverflow.com/questions/17311645/…, чтобы активировать сгенерированную ссылку, и вам не потребуется вмешательство пользователя. Вы можете указать Атрибут HTML5 download, чтобы предложить имя, указанное в многоДругиеответы.

drzaus 02.07.2014 19:11

Это отличный способ обхода Safari. Используйте Modernizr, чтобы определить, когда атрибут загрузки не поддерживается, и обновите текст ссылки!

littledynamo 01.06.2016 00:44

Взгляните на эту ссылку: 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

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

к сожалению, это не загружается.

James Khoury 30.05.2011 06:47

это обсуждение касалось расширения предложенный для формата URI данных - оно не было реализовано.

Alnitak 30.05.2011 12:14

Реализовано или нет, но с существующей поддержкой произвольных параметров это было бы здорово.

Dan Lugg 21.12.2012 21:28

Я немного искал источники 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 является высшим авторитетом в отношении того, что существует. :)

Gleno 05.06.2011 14:30

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

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

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

Это единственный полный ответ. Нет, вы не можете этого сделать с data: URI. Да, вы можете указать имя файла для ссылки для загрузки с помощью чистого Javascript. Спасибо!

Biovisualize 17.11.2011 20:03

@BioDesign: он работает даже с данными: URI в хроме. См .: jsfiddle.net/pYpqW

Senseful 17.01.2012 09:36

но вы не можете сделать это с window.location.replace. если вы, например, хотите создать данные: uri или один, сгенерированный window.URL.createObjectURL, и загрузить его как файл, вам нужно будет создать <a> и щелкнуть по нему: jsfiddle.net/flyingsheep/wpQtH (нет, $(...).click() не работает)

flying sheep 16.03.2012 22:31

Это функция WHATWG, которую реализует Google, но поскольку это (неофициальный) стандарт, он может стать популярным. whatwg.org/specs/web-apps/current-work/multipage/…

orip 02.08.2012 15:58

Только если бы весь браузер был похож на Chrome ... [вздох]

streetlight 14.11.2012 17:25

@flyingsheep $('<a href = "data:text/plain,Test" download = "test.txt">')[0].click(), похоже, здесь отлично работает (Chrome 23) (примечание: я использовал собственный метод click, а не jQuery). Демо: jsfiddle.net/2zsRW

Rob W 06.12.2012 16:34

но в firefox работает только jsfiddle.net/2zsRW/1. может быть, какая-то политика или ошибка одного и того же происхождения? (в сторону: поскольку атрибут загрузки еще не реализован, он просто заменяет фрейм вместо загрузки)

flying sheep 06.12.2012 17:08

@flyingsheep, похоже, они применяют политику одного и того же происхождения в Firefox. «В Firefox 20 этот атрибут учитывается только для ссылок на ресурсы с одинаковым происхождением». developer.mozilla.org/en-US/docs/Web/HTML/Element/a В моем тестировании Chrome не имеет этого ограничения.

William Denniss 19.12.2013 10:17

@Pacerier, спасибо, что обновляете ответ, но когда это срок "в настоящее время"

jcolebrand 03.03.2015 20:26

@jcolebrand, это по дате редактирования, которую можно увидеть под постом. Кстати, где комментарий, в котором ты назвал меня придурком?

Pacerier 12.03.2015 09:24

Проблема с этим решением заключается в том, что файл воля загружается, если пользователь щелкает ссылку. Что, если вы просто хотите указать имя файла, если пользователь щелкнет правой кнопкой мыши + Сохранить ссылку как ...?

phn 31.08.2016 18:03

Почему это не один из самых популярных ответов?

FluorescentGreen5 07.05.2017 10:23

@streetlight 8 лет спустя, и Chrome заблокировал все URL-адреса данных верхнего кадра по соображениям безопасности. Таков цикл технологических компаний.

Seph Reed 26.11.2020 02:29

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

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

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

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

Интересный сценарий, но он требует, чтобы сервер получил ответ и правильно отправил его? jsfiddle.net/hZySf

James Khoury 13.01.2012 06:03

Я не уверен, откуда генерируется файл ... этот файл хранится в кодировке base64? (Я не слишком знаком с base64)

streetlight 14.11.2012 17:47

@streetlight: «Файл» (т.е. данные) генерируется Javascript. Контекст этого проекта (и, вероятно, большей части здесь) предполагает, что у вас есть способ получить желаемые данные в переменной JS. Разница в том, что вместо того, чтобы представлять его пользователю через URI data:..., этот скрипт создает форму для POST его на сервер. И затем сервер предположительно повторяет его прямо как ответ HTTP «загрузить» (то есть с соответствующим заголовком Content-Disposition, указывающим имя файла).

Andrzej Doyle 14.01.2013 15:22

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

образец:

<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.

fregante 08.09.2014 04:32

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

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}

Я знаю, что все эти другие ответы говорят об этом, сработало с первой попытки в Chrome 30.

Michael J. Calkins 23.10.2013 18:43

Сейчас это происходит, но это не всегда было так просто. Многие из этих ответов были получены много лет назад. И они также работают для других браузеров.

Holf 26.10.2013 14:09

Обратитесь к http://caniuse.com/#feat=download для получения полного списка совместимых браузеров.

tixastronauta 13.02.2014 14:24

@tixastronauta: Несмотря на информацию на этой странице, не работает в моем firefox 44. Хорошо работает в Chrome. 48

Luis A. Florit 17.02.2016 16:43

Привет, @Holf, есть ли способ добавить тип или расширение файла или его так же просто, как указать его как имя файла?

Fraccier 31.05.2016 17:57

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

barbarian 21.09.2016 17:09

К сожалению, это тот же предел в 2 МБ в Chrome при использовании с URL-адресом данных: stackoverflow.com/a/41755526/1024735

kevinmicke 13.12.2018 02:02

Вот версия 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 04.03.2014 18:56

@ p0lar_bear вы должны получить это исключение с любым jQuery, потому что получение [0] из любого «элемента jQuery» должно возвращать первый элемент DOM, который он представляет, что по существу «выводит вас из» jQuery.

drzaus 11.12.2014 23:16

На самом деле вам вообще не нужно добавлять / удалять элемент - см. Комментарии на stackoverflow.com/a/17311705/1037948

drzaus 11.12.2014 23:18

Только 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+).

fregante 07.10.2014 22:09

Для более полного решения я предлагаю использовать downloadjs в npm

fregante 28.09.2016 19:43

У меня это работает, но после этого страница браузера обновляется. Хотите знать, как этого избежать?

user6269864 18.11.2016 08:46

Не работает в Chrome для размера файла> 2 МБ из-за ограничения Chrome stackoverflow.com/questions/695151/…

Pranav Singh 06.02.2017 14:12

Предел относится к URI data:, о чем упоминается в вопросе. Этот ответ также работает с Blobs и всем, что имеет URI

fregante 06.02.2017 16:27

Работал как шарм. Успешно справился.

Aarmora 01.05.2017 22:00

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

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

Интересно! Однако пока поддержка кажется довольно мелкой: caniuse.com/#feat=serviceworkers

tuomassalo 06.02.2015 23:49

Есть ли способ "ответить" другим прямым URL-адресом файла?

Iulian Onofrei 10.02.2016 01:10
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

Sebastian Brosch 25.11.2015 16:29

этот ответ - мусор

Jonathan Taylor 20.07.2017 19:54

Этот работает с 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.

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

Вы действительно можете добиться этого в 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

Другие вопросы по теме