已经支持用Data URL(RFC2397)来引用,首先看下面

2019-11-26 16:35栏目:前端开发
TAG:

了解HTML/HTML5中的download属性

2016/04/07 · HTML5 · 5 评论 · download

原文出处: 张鑫旭(@张鑫旭)   

一、download属性是个什么鬼?

首先看下面这种截图:
图片 1

如果我们想实现点击上面的下载按钮下载一张图片,你会如何实现?

我们可能会想到一个最简单的方法,就是直接按钮a标签链接一张图片,类似下面这样:

<a href="large.jpg">下载</a>

1
<a href="large.jpg">下载</a>

但是,想法虽好,实际效果却不是我们想要的,因为浏览器可以直接浏览图片,因此,我们点击下面的“下载”链接,并是不下载图片,而是在新窗口直接浏览图片。

下载

看我的眼睛,图片 2

于是,基本上,目前的实现都是放弃HTML策略,而是使用,例如php这样的后端语言,通过告知浏览器header信息,来实现下载。

header('Content-type: image/jpeg'); header("Content-Disposition: attachment; filename='download.jpg'");

1
2
header('Content-type: image/jpeg');
header("Content-Disposition: attachment; filename='download.jpg'");

然而,这种前后端都要操心的方式神烦,现在都流行前后端分离,还搅在一起太累了,感觉不会再爱了。

那有没有什么只需要前端动动指头就能实现下载的方式呢?有,就是本文要介绍的download属性。

例如,我们希望点击“下载”链接下载图片而不是浏览,直接增加一个download属性就可以:

<a href="large.jpg" download>下载</a>

1
<a href="large.jpg" download>下载</a>

没错,你没有看错,就这么结束了,不妨点击后面的链接试试:下载

结果在Chrome浏览器下(FireFox浏览器因为跨域限制无效):
图片 3

不仅如此,我们还可以指定下载图片的文件名:

<a href="index_logo.gif" download="_5332_.gif">下载</a>

1
<a href="index_logo.gif" download="_5332_.gif">下载</a>

如果后缀名一样,我们还可以缺省,直接文件名:

<a href="index_logo.gif" download="_5332_">下载</a>

1
<a href="index_logo.gif" download="_5332_">下载</a>

截图为虚,操作为实:下载

Chrome下的截图效果示意:
图片 4

一个大写的酷里!

准备工作

想要将canvas元素当前显示的内容生成为图像文件,我们首先要获取canvas中的数据,在HTML5 <canvas>元素的标准中提供了toDataURL()的方法可以将canvas中的内容生成为指定格式的DataURL,使用方法如下:

// 假设有一个id为cvs的canvas元素
var dataurl = document.getElementById('cvs').toDataURL('image/png');

我们现在需要将DataURL生成为一个png类型的图像文件,并且这个操作是在本地完成的,不需要服务器帮助生成文件。以下提供两种方法:

【Data URL】

二、浏览器兼容性和跨域策略

图片 5

然而,caniuse展示的兼容性只是个笼统,根据鄙人的实地测试,事情要比看到的复杂。

主要表现在跨域策略的处理上,由于我手上没有IE13,所以,只能对比Chrome浏览器和FireFox浏览器:

如果需要下载的资源是跨域的,包括跨子域,在Chrome浏览器下,使用download属性是可以下载的,但是,并不能重置下载的文件的命名;而FireFox浏览器下,则download属性是无效的,也就是FireFox浏览器无论如何都不支持跨域资源的download属性下载。

而,如果资源是同域名的,则两个浏览器都是畅通无阻的下载,不会出现下载变浏览的情况。
图片 6

是否支持download属性的监测
要监测当前浏览器是否支持download属性,一行JS代码就可以了,如下:

var isSupportDownload = 'download' in document.createElement('a');

1
var isSupportDownload = 'download' in document.createElement('a');

方法一 利用HTML5 <a>标签的download属性

在HTML5标准中,<a>标签拥有一个新的属性download,download属性用来指明该超链接指向的目标是应该被下载的文件,例如

<a href="http://www.jianshu.com" download>下载</a>

download属性可以被赋值,用来指明下载文件的名称,例如

<a href="http://www.jianshu.com" download="index.html">下载</a>

最新的HTML5浏览器中,已经支持用Data URL(RFC2397)来引用“外部”资源了。

三、结束语

除了图片资源,我们还可以是PDF资源,或者txt资源等等。尤其Chrome等浏览器可以直接打开PDF文件,使得此文件格式需要download处理的场景越来越普遍。

此HTML属性虽然非常实用和方便,但是兼容性制约了我们的大规模应用。

同时考虑到很多时候,需要进行一些下载的统计,纯前端的方式想要保存下载量数据,还是有些吃紧,需要跟开发的同学配合才行,还不如使用传统方法。

所以,download属性的未来前景在哪里?当下是否可以直接加入到实际项目?还需要我们一起好好想想。其实使用JS实现download属性的polyfill并不难,但是,考虑到为何不所有浏览器都使用polyfill的方法,又觉得为了技术而技术是不太妥当的。

总之,先放着心上,再观察观察。

1 赞 3 收藏 5 评论

图片 7

示例

现在,我们可以通过将DataURL赋值给a标签的href属性,并且使用download属性使其转变为可下载的图片。

var dataurl = document.getElementById('cvs').toDataURL('image/png');
var a = document.createElement('a');
a.href = dataurl;
a.download = "sample";
a.click();

比如下面的链接,在HTML5浏览器中点击后,会转到一个新页面,显示“Hello Data URL!”字样。

兼容性

目前只有Chrome和FireFox支持download属性

[html] 
<a href="data:text/plain,Hello Data URL!">Hello</a> 
如果文本内容包含特殊字符怎么办?Data URL也是一种URL,也可以使用通用的URL转义编码:

方法二 修改DataURL的Mime-type

如果我们直接将获得的DataURL赋值给a标签的href属性,在点击链接后浏览器只会在新窗口打开图片,并不会直接执行下载。我们可以修改DataURL的Mime-type为octet-stream,强制让浏览器下载。

[html] 
<a href="data:text/html;charset=utf8,%3Ch1%3E%E4%BD%A0%E5%A5%BD%3C/h1%3E">URL escaped</a> 
上面的例子都是纯文本数据。其实Data URL也可以表示二进制数据,用Base64编码即可(当然URL转义也能实现)。
下面是一个表示GIF图片的Data URL(引用自RFC2397):

示例

var dataurl = document.getElementById('cvs').toDataURL('image/png').replace("image/png", "image/octet-stream");
var tmpa = document.createElement('a');
a.href = dataurl;
a.target = "_blank";
a.click();

[html] 
<a href="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7">Larry</a> 
也不是所有的二进制文件格式都必须编码,当实际数据不包含特殊字符的时候,不编码也是可以的:

兼容性

这个方法对于大部分主流浏览器都可用,但是octet-stream并不包含文件名和扩展名的信息,所以使用这个方法下载下来的文件是没有扩展名的文件,浏览器可能默认的命名为“下载”或者“unknown”

[html] 
<a href="data:application/octet-stream,12345">octet-stream</a> 
上面的链接都可以点右键“另存为”本地磁盘文件,这个过程就像通常下载远程文件的操作一样。
这样的话,理论上我们可以将任何数据转化为一个Data URL链接,以便让用户“下载”。

【自动下载和默认文件名】
上面已经实现了生成文件数据并保存到本地的功能,但是还有不足:

对于浏览器能够显示的MIME类型,点击链接的话会直接在浏览器中显示,比如纯文本、HTML以及图片等类型。

若手动将链接另存,Chrome 22中文版弹出的保存框默认主文件名永远为“下载”,Firefox 16则是一串莫名其妙并以.part结尾的字符串做默认名。

对于浏览器不能显示的MIME类型,Chrome 22和Firefox 16都会自动调用下载功能。但是Chrome中文版下载的默认主文件名仍然总为“下载”,Firefox 16则还是莫名其妙的字符串。

不过,Chrome 22中已经对<a>元素增加了一个新的标签属性“download”来解决这个问题。

[html] 
<a href="data:text/plain,Hello Data URL!" download="hello.txt">hello</a> 
<a href="data:text/html;charset=utf8,%3Ch1%3E%E4%BD%A0%E5%A5%BD%3C/h1%3E" download="URL escaped.html">URL escaped</a> 
<a href="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7" download="Larry.gif">Larry</a> 
<a href="data:application/octet-stream,12345" download="octet-stream.bin">octet-stream</a> 
对于指定了download标签属性的链接,点击后,Chrome 总是会执行下载操作,并且下载保存的默认文件名即为download的属性值。
遗憾的是Firefox 16还不支持这样的属性。

另外,Chrome下载默认不提示文件保存位置和名称。若希望每次都提示,可在Chrome的设置中修改。

【附】

以往要在浏览器中实现这么一个另存为的功能,可以用IE的document.execCommand('SaveAs')模拟,但是对复杂的数据格式就没法处理了。

或者配合服务端程序可以处理复杂的数据,但处理过程也变复杂了,纯粹的本地应用还必须搭建一个额外的服务器。

再就是利用HTA+FSO/ADO.Stream来生成文件,但是各代Windows系统中没用统一完善的通用对话框控件来实现“另存为”对话框,要么单独注册,要么利用Office中的对话框组件,或者其他方式模拟实现,结果这个非核心功能导致整个实现复杂了许多。

对于更复杂的数据,Data URL可能不太够用,这时可以考虑功能更强大的HTML5 File API,使用createObjectURL()方法可以得到比Data URL更短的URL,这里不作具体叙述。

关于Chrome 22支持的<a>的标签属性download,我是从“zip.js”(一个开源的zip压缩解压JS库)的demo中发现的。实现此属性最早的Chrome版本未知。

URL】 最新的HTML5浏览器中,已经支持用Data URL(RFC2397)来引用外部资源了。 比如下面的链接,在HTML5浏览器中点击后,会转到一个新...

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于前端开发,转载请注明出处:已经支持用Data URL(RFC2397)来引用,首先看下面