有没有办法在使用 data: URI 时指定建议的文件名?
Posted
技术标签:
【中文标题】有没有办法在使用 data: URI 时指定建议的文件名?【英文标题】:Is there any way to specify a suggested filename when using data: URI? 【发布时间】:2010-09-21 23:43:03 【问题描述】:例如,如果您点击链接:
data:application/octet-stream;base64,SGVsbG8=
浏览器将提示您下载一个文件,该文件包含超链接本身中以 base64 形式保存的数据。有没有办法在标记中建议默认名称?如果没有,是否有 javascript 解决方案?
【问题讨论】:
可能与此问题无关,但如果这不是服务器或旧浏览器障碍,我建议使用 blob 的 & URL.createObjectURL 部分浏览器支持mediatype的可选参数“name”:data:application/pdf;name=document.pdf;base64,BASE64_DATA_ENCODED
我遇到了 Firefox pdf.js 的问题,如果它无法从数据 uri 中提取文件名,它在某些情况下往往会挂起。见***.com/questions/45585921/…
@mems 哪些浏览器支持“name”参数?你能指点我一些参考文件吗? (我的 google-fu 让我失望了)。
@DimuDesigns 至少是当时的 Firefox。似乎不再是这种情况了。它与 MIME Content-Type (!= Content-Disposition) "name" 参数有关(不在 RFC 中?)
【参考方案1】:
使用download
属性:
<a download='FileName' href='your_url'>
The download
attribute works on Chrome、Firefox、Edge、Opera、桌面版 Safari 10+、ios Safari 13+,而不是 IE11。
【讨论】:
@BioDesign:它甚至适用于 chrome 中的 data:URI。见:jsfiddle.net/pYpqW 但是你不能用window.location.replace
来做。如果你例如想要创建一个 data:uri 或由window.URL.createObjectURL
生成的一个,并将其下载为文件,您必须创建一个 并单击它:jsfiddle.net/flyingsheep/wpQtH(不,$(...).click()
不起作用)
只有在所有浏览器都像 Chrome 一样... [叹息]
@flyingsheep $('<a href="data:text/plain,Test" download="test.txt">')[0].click()
似乎在这里工作正常(Chrome 23)(注意:我使用了原生的 click
方法,而不是 jQuery 的方法)。演示:jsfiddle.net/2zsRW
@flyingsheep 似乎他们正在 Firefox 中执行同源策略“在 Firefox 20 中,此属性仅适用于指向同源资源的链接。” developer.mozilla.org/en-US/docs/Web/html/Element/a 在我的测试中,Chrome 没有这个限制。【参考方案2】:
如今,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 有没有办法添加文件类型或扩展名,或者就像文件名一样简单?【参考方案3】:仅 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(don't support the download
attribute)将使用默认名称下载文件或者他们只会在新标签中显示,如果它是受支持的文件类型:图像、视频、音频文件……
【讨论】:
两个演示在 Chrome 38 中对我来说都可以正常工作(但它们应该在 Chrome 14+ 中工作) 为了更完整的解决方案,我建议使用downloadjs
on npm
它适用于我,但之后浏览器页面会刷新。想知道如何防止这种情况发生?
文件大小在 chrome 中不可用 > 2MB 由于 chrome ***.com/questions/695151/… 的限制
限制属于data:
URI,这就是问题提到的。这个答案也适用于 Blob 和其他任何有 URI 的东西【参考方案4】:
根据RFC 2397,不,没有。
在<a>
元素中似乎也没有任何attribute 可以使用。
然而 HTML5 随后在 <a>
元素上引入了 download
属性,尽管在撰写本文时支持并不普遍(例如,不支持 MSIE)
【讨论】:
第二句话在撰写本文时是正确的,但 isn’t anymore。不过,到目前为止,它还没有被广泛实施。 见this comment了解更多信息:) @flyingsheep,它已广泛实施。 我写那条评论还不是三年前 文件过长下载失败【参考方案5】:我在 netwerk/protocol/data/nsDataHandler.cpp 中查看了一些 firefox 源代码
数据处理程序仅解析内容/类型和字符集,并查看是否存在“;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 是存在的最终权威。 :)【参考方案6】:以下 Javascript sn-p 通过使用链接的新“下载”属性并模拟点击在 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 兼容性的扩展答案。【参考方案7】:没有。
整个目的是它是一个数据流,而不是一个文件。数据源不应该知道用户代理将其作为文件处理......而且它没有。
【讨论】:
data:
的目的是将内部数据块捏造成URL格式,而无需从基于协议的源读取它. @silex 答案中的链接表明,即使尚未实现,建议首选名称write 的能力也被认为是有用的。
@Alnitak:有用吗?绝对地。技术上合适吗?还是不服气。 :)
@Tomalak 考虑加载数据和保存数据之间的区别——仅仅因为 blob 在数据中内联编码:URL 并不意味着它不应该有一个首选名称来保存它.
但是你关于它的“全部目的”的说法是错误的。 data:
是专门为允许(小)inline 内容以一种捏造在一起的 URL 格式出现的,这样它就可以被诸如图像标签之类的东西使用,而无需单独的 HTTP 请求。 HTML 表示 img src
属性的内容必须是 URL,这就是 RFC 2397 创建的内容。没有“数据源”。
@Alnitak:没错。没有数据源。没有上下文。 URI 是数据。【参考方案8】:
您可以将下载属性添加到锚元素。
样本:
<a download="abcd.cer"
href="data:application/stream;base64,MIIDhTC......">down</a>
【讨论】:
【参考方案9】:使用service workers,这终于是真正意义上的可能了。
-
创建一个虚假的 URL。例如 /saveAs/myPrettyName.jpg
在
<a href, <img src
中使用 URL,window.open( url ),绝对是可以使用“真实”URL 完成的任何事情。
在 Worker 内部,捕获 fetch 事件,并以正确的数据进行响应。
浏览器现在会建议 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 “响应”?【参考方案10】:看看这个链接: 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
在讨论的其余消息中也有一些信息。
【讨论】:
很遗憾这没有下载。 此讨论是针对数据 URI 格式的提议扩展 - 它尚未实现。 实现与否,在现有对任意参数的支持下,这将是一个很好的选择。【参考方案11】:Google 代码上有一个对我有用的小变通脚本:
http://code.google.com/p/download-data-uri/
它添加一个包含数据的表单,提交它,然后再次删除该表单。哈基,但它为我完成了工作。需要 jQuery。
此主题在 Google 代码页面之前出现在 Google 中,我认为将链接也放在此处可能会有所帮助。
【讨论】:
有趣的脚本,但它确实需要服务器获取响应并将其发回,对吗? jsfiddle.net/hZySf 我不确定文件是从哪里生成的。该文件是否存储在 base64 编码中? (我对base64不太熟悉) @streetlight:“文件”(即数据)由 Javascript 生成。该项目的上下文(可能是这里的大多数)假设您有某种方法可以将所需的数据放入 JS 变量中。不同之处在于,该脚本不是通过data:...
URI 将其呈现给用户,而是创建一个表单以将其发布到服务器。然后服务器可能会直接将其作为 HTTP“下载”响应回显(即使用适当的 Content-Disposition 标头指定文件名)。【参考方案12】:
这是一个基于 Holf 版本的 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 获得该异常,因为从任何“jQuery 元素”获取 [0]
应该返回它所代表的第一个 DOM 元素,这实质上是“带你离开”jQuery。
您实际上根本不需要附加/删除元素——请参阅***.com/a/17311705/1037948的 cmets 【参考方案13】:
这个适用于 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
【讨论】:
【参考方案14】:(此答案已被新技术弃用,但出于历史兴趣将保留在这里。)
这有点骇人听闻,但我以前也遇到过同样的情况。我在 javascript 中动态生成一个文本文件,并希望通过使用 data-URI 对其进行编码来提供它以供下载。
这可以通过minor主要的用户干预来实现。生成链接<a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>
。正如我所说,这很不优雅,但如果您不需要专业的解决方案,它就可以工作。
首先使用 flash 将名称复制到剪贴板可以减轻这种痛苦。当然,如果您让自己使用 Flash 或 Java(我认为现在浏览器支持越来越少?),您可能会找到另一种方法。
【讨论】:
这不是解决方案,也不符合要求。对不起。 大声笑@“次要用户干预”。让用户为你做所有事情并不是“轻微的用户干预”。 将此与***.com/questions/17311645/… 结合以触发生成的链接,您不需要用户干预。您可以指定HTML5download
attribute 来建议many other answers 提到的名称。
这是 Safari 的一个很好的解决方法。使用 Modernizr 检测何时不支持下载属性并更新链接文本!【参考方案15】:
<a href=.. download=.. >
适用于左键单击和右键单击-> 将链接另存为..,
但<img src=.. download=.. >
不适用于右键单击 -> 将图像另存为.. ,建议使用“Download.jped”。
如果你将两者结合起来:<a href=.. download=..><img src=..></a>
它适用于左键单击,右键单击 -> 将链接另存为..,右键单击 -> 将图像另存为..
你必须写两次 data-uri(href 和 src),所以对于大的图像文件,最好用 javascript 复制 uri。
使用 Chrome/Edge 88 测试
【讨论】:
【参考方案16】: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 () );
【讨论】:
请为您的答案添加更详细的解释 - ***.com/help/how-to-answer 这个答案很垃圾【参考方案17】:您实际上可以在 Chrome 和 FireFox 中实现这一点。
试试下面的网址,它会下载使用过的代码。
data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==
【讨论】:
以上是关于有没有办法在使用 data: URI 时指定建议的文件名?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 Spring Data @Query 注释值中使用常量?