了解HTML/HTML5中的download属性

这篇文章发布于 2016年04月6日,星期三,23:32,归类于 HTML相关。 阅读 190073 次, 今日 9 次 68 条评论

 

一、download属性是个什么鬼?

首先看下面这种截图:
下载按钮

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

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

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

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

下载

看我的眼睛,go die

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

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

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

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

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

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

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

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

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

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

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

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

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

Chrome下的截图效果示意:
下载同时更改名称

一个大写的酷里!

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

兼容性如下图:

Download属性的兼容性

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

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

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

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

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

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

三、结束语

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

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

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

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

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

补充于2017-07-04
如果需求是直接使用JS触发浏览器的下载,可以看看这篇文章:“使用JS让文本字符串作为html或JSON文件下载”。

(本篇完)

分享到:


发表评论(目前68 条评论)

  1. 贤海说道:

    在最新的chrome浏览器下,同源下载文件,使用download属性也无法更改文件名了,请问有其他方式么

  2. AICC说道:

    a标签下载无法在下载成功以后有一个提示,下载提示这一块有什么思路点拨一下的么

  3. jack说道:

    如何监听下载完成呢

  4. xgqfrms说道:

    # HTML5 download 执行条件

    1. 同一个域名下的资源

    2. http only

    3. 绝对路径/相对路径 都可以

  5. bob说道:

    请问在webview里,这个功能不生效怎么办?比如在facebook里,想在网页生成图片并下载

  6. tests说道:

    现在chrome里面,跨域资源好像不能下载了

  7. 家福说道:

    完整的url路径chrome 70.0.3538.77 不能下载,还没找到方法

    • hcc说道:

      本地图片可以实现下载,但是完整的路径 chrome 70.0.3538.102 是打开图片,不是下载。一度怀疑自己。

    • hcc说道:

      应该是下面所说的造成的
      “抛开浏览器兼容性,还有几点限制:

      href 所指向的地址,必须与当前网站同源,否则

      chrome 65.0.3325.181 下测试,只能下载不能改名
      chrome 69.0.3497.92 中已经严格遵循同源策略的限制,如果加载了非同源的内容,download 属性将失效,等效导航功能。
      Firefox 61.0.1同上”

  8. 刘伟波说道:

    如果是其他域名下的文件download就会无视

  9. chrome download属性 下载MP3文件 不执行下载直接打开新页播放说道:

    前辈,您好 我在使用a标签下载mp3 格式文件的时候 为什么它并不执行下载 而是直接跳到一个新的页面播放了, 这种应该怎么解决啊

  10. ytxmobile说道:

    Firefox可以通过打开about:config,将security.fileuri.strict_origin_policy一项的值修改为false以实现跨域下载。

  11. 谷歌download下载出现:下载失败-网络错误说道:

    谷歌浏览器通过a标签的download属性下载图片,出现下载失败-网络错误。。。前辈有没有遇到过解决过呀?求指教~~~~

  12. 尼克陈说道:

    棒啊 又帮到我的一个需求

  13. ig 照片下載说道:

    移动端统统不兼容

  14. 静默说道:

    在微信中无法使用download属性

  15. 说道:

    移动端(主要是安卓)怎么下载?点击没有反应

  16. Jun说道:

    大神,最近在遇到一个问题,在所有浏览器都可以,但是好像safari不支持,我在stackflow搜了半天找不到解决方案,特来请教!
    谢啦!
    $http({
    url: ‘××××××××××××××××××××××××/’,
    method: “POST”,
    data: {‘date’:day},
    headers: {
    ‘Content-type’: ‘application/json’
    },
    responseType: ‘arraybuffer’
    }).success(function (data, status, headers, config) {
    var headerType = ‘application/zip’,fileType = ‘-GMT.zip’;
    if(headers()[‘content-type’]==’application/vnd.openxmlformats-officedocument.spreadsheetml.sheet’){
    headerType = “application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”;
    fileType = “-GMT.xlsx”;
    }
    var blob = new Blob([data], {type: headerType});
    var objectUrl = URL.createObjectURL(blob);
    var a = document.createElement(“a”);
    document.body.appendChild(a);
    a.download = “×××××××××××”+ day +fileType;
    a.href = objectUrl;
    a.click();
    a.remove();
    //window.open(objectUrl);
    //FileSaver.saveAs(data);
    }).error(function (data, status, headers, config) {
    ××××

    });

  17. Lili说道:

    请问您说还不如使用传统方法 那传统方法是什么??

    • 小庞说道:

      我想你要的答案就是这个吧?我也是在别的群里看到相关问题然后百度过来得,看来download还得等等普及了才能用啊。这是那个老方法得链接,你看看吧http://www.xiaoxiaohan.com/php/3.html(别人写的)
      ====来自一只小菜鸟

    • Leo说道:

      传统方法是设置 Http Header,Content-Disposition: attachment

  18. lee说道:

    火狐下载下来没有后缀怎么破

  19. llllllllllll说道:

    好像是href是绝对路径就不行

  20. llllllllllll说道:

    发现用了download直接点击下载,是会用原来文件名的,除非是,右键,链接另存为,才会使用download的参数做为文件名。。。

    • 阳阳说道:

      同感,IE不支持,chrome和360浏览器右键,链接另存为,才会使用download的参数做为文件名;firefox是支持的

  21. 不知不觉说道:

    在pc上确实可以下载,但是在手机上好像是在新窗口打开了图片诶,大神,这个怎么解决

  22. HEarTache psR.说道:

    哈哈,觉得前辈应该是个蛮开朗的逗x.
    原谅对前辈如此模糊仓促的评价, 学习一个技术看到了前辈发的一篇Blog,追到了这里,初看前辈头像, 我擦 跟老家的邻家大哥兼逗x连坐太像了。 之后又看到了前辈是09集华中科技大的高材生, 曾经自己无限向往并为之倾覆心血的目标。 向往之久, 可最后还是因为一些琐事,未能达到自己的目标成了一生的遗憾。 初来乍到跟前辈打个招呼, 未来会长期光顾前辈的小窝学习。 啊你哦塞哟~

  23. trance说道:

    我就想问问 右侧一直跟着的蓝色大面包是个啥~~

  24. tony说道:

    想问你每次写的文章上展示的浏览器兼容性是通过什么工具去测试的?DEMO都去测过每个浏览器的兼容性吗

  25. 愤怒的老鸟说道:

    旭哥你在慕课上面relative那个课 relative单词错了

  26. 小白说道:

    感觉你写的前端知识好多,我觉得有必要一个一个的全部读完。

  27. 雪板烧说道:

    兼容性问题始终是个大问题!

  28. 66666说道:

    别的不说,牛逼送上

  29. 不新鲜的萝卜皮说道:

    发现个展示上的小问题,网站导航栏下面多了一个句号”。”

  30. aalouie说道:

    我很怀念张含韵

  31. 亚信朱威峰说道:

    兄弟,顶你啊!最近查找东西的时候总是搜到您的这个网站,今天翻看了下,您已经坚持了六年了,光是这份毅力就了不起,在这个充满浮躁的世界里,向您致敬!您对技术日益精湛的追求,值得我们这些后备学习!

    —-一个学了七年地质毕业就转行的小弟。

  32. 土鸡价格说道:

    HTML/HTML5中的download属性,没记错的话应该是加载吧

    • 小丫说道:

      download的是下载的意思,onload的才是加载的意思。除开前端常识,这也是英语单词的本意。

  33. 小泼墨说道:

    chrome,ff还好,但是在safari还有移动端的浏览器上,download兼容性还是太差

  34. gap year说道:

    前段时间,我还在弄这个问题,知道了download属性的方法。不过好像兼容有问题,ie没用

  35. 苏茂林说道:

    很赞,可以在新的项目里试试图片的下载

  36. muzuiget说道:

    第二个下载链接用 download=”” 在 Firefox 45 里还是会在浏览器打开的。

  37. Chitanda说道:

    前辈这里有个小问题:第二个截图的实例代码和图上的后缀名不一样。。一个是gif一个是jpeg..开始没反应过来