html5的文件类型声明(浅析HTML5中的download属性使用)
html5的文件类型声明
浅析HTML5中的download属性使用随着前端技术的发展,越来越多的业务场景中需要前端来处理文件下载。在众多的方法中,通过 <a>
标签的 download 属性实现下载是其中常见也是比较简单的一种方法。
download 属性介绍
常规的 <a>
标签通过 href 实现链接跳转,如果只想下载文件而不是跳转预览,最好的方式是在 <a>
标签中添加 download
属性,就能很简单地实现下载操作。
download
是 HTML5 中 <a>
标签新增的一个属性,此属性会强制触发下载操作,指示浏览器下载 URL 而不是导航到它,并提示用户将其保存为本地文件,例如:
<a href="result.jpg" alt="html5的文件类型声明(浅析HTML5中的download属性使用)" border="0" />
如果缺少 download
属性,点击 "download" 会直接变成预览图片,当添加 download
属性后则会触发图片的下载。
目前 download
属性的兼容性如caniuse 中所展示的:
可以以看到,大部分主流的浏览器基本都已经支持 download
属性,而 IE 的表现一如既往的感人,目前许多 Window 系统仍然在使用 IE ,这也是许多业务需求需要考虑的。这种兼容性问题限制了 download
的更广泛应用。
动态资源下载
面对一些动态内容下载的业务场景,即图片等资源的地址并不是固定的(例如一些在线绘图工具所生成的图片),只使用 HTML 无法满足需求。为了能够满足不同的 URL 下载,可以通过JS 实现一个动态触发 URL 下载的方法。
function download(href, filename='') { const a = document.createElement('a') a.download = filename a.href = href document.body.appendChild(a) a.click() a.remove() }
需要注意的是,代码中对创建的 <a>
进行的 appendChild
和 remove
操作主要是为了兼容 FireFox 浏览器,在 FireFox 浏览器下调用该方法如果不将创建的 <a>
标签添加到 body 里,点击链接不会有任何反应,无法触发下载,而在 Chrome 浏览器中则不受此影响。
上述的方法可以实现同源资源的下载。但在很多场景中,还需要处理跨域资源。遗憾的是, download
属性目前仅适用于 同源 URL ,即如果需要下载的资源地址是跨域的, download
属性就会失效,点击链接会变成导航预览。
测试:点击下载,结果只是预览而无法下载图片。
注: Chrome65 之前是支持 download
属性触发文件跨域下载的,之后则严格遵循同源策略,无法再通过 download
属性触发跨域资源的下载。而 FireFox 一直不支持跨域资源的 download
属性下载。
文件命名问题
download
属性不仅可以触发下载,也能指定下载文件名:
<a href="test.jpg" alt="html5的文件类型声明(浅析HTML5中的download属性使用)" border="0" />
如果下载文件的后缀与源文件保持一致,可以设置缺省文件名:
<a href="test.jpg" alt="html5的文件类型声明(浅析HTML5中的download属性使用)" border="0" />
笔者曾遇到过一个问题,通过 <a>
标签触发跨域资源下载,代码与上述的 download 方法基本相同,只是在设置 download
属性的地方有点不同:
a.setAttribute(download, true)
结果在老版本的 Chrome 浏览器中出现了如下情况。
下载文件名成了 true
。很明显,浏览器将 download
属性值读成了文件名。
经过分析,出现上述问题主要是因为:
1. 首先本不该将 download
设为 true
, download
与 disabled
这种类型的属性值不同,它与文件名直接相关联。而且对于这种前后端响应式下载的方式, download
属性并不是必要的。
2. 在 Chrome 的早期版本不仅支持跨域资源的 download
属性下载,而且还可以通过 download
重置跨域资源的文件名,因此才会出现上述这种情况。
前后端配合完成文件下载的业务场景,一般是由后端设置响应头中的 Content-Disposition
信息来实现。
在 HTTP 场景中,Content-Disposition 第一个参数或者是 inline(默认值,表示回复中的消息体会以页面的一部分或者整个页面的形式展示),或者是 attachment(意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将 filename 的值预填为下载后的文件名)。
如果在响应头中设置了 Content-Disposition
,前端也在对应链接的 <a>
标签中添加了 download
属性,那么此时命名规则:
如果 HTTP 头中的 Content-Disposition 属性赋予了一个不同于此属性的文件名,HTTP 头属性优先于此属性。
经过测试发现,当 HTTP 头中 Content-Disposition
不为空时:
在 Chrome 浏览器中,不管 HTTP 头中 Content-Disposition
的第一个参数被设为 attachment 还是 inline ,只要设置了 filename, download
就无法重置文件名。相反,当 filename 为空时, download
属性值会被设为文件名。 在 FireFox 浏览器中,浏览器只会读取 Content-Disposition
的 filename 值,若是filename 为空,则取源文件名。此时 download
无论如何都无法重置文件名。
总结一下: 未在响应头设置 Content-Disposition
信息(例如一般直接定位资源的同源URL), download
属性可以重置文件名。若后端在 Content-Disposition
字段中已经设置了 filename,以 filename 值为准。
对于后端已经设定了文件名的情况下,如果仍然想要对文件名进行重置,该如何处理呢?
Blob: URL
关于 download
属性还有介绍:
尽管 HTTP URL 需要位于同一源中,但是可以使用 blob: URL 和 data: URL ,以方便用户下载使用 JavaScript 生成的内容(例如使用在线绘图 Web 应用程序创建的照片)。
Blob
(Binary Large Object)即二进制大对象,这个我们并不陌生,一些数据库将Blob用来表示存储二进制文件的字段类型。File 接口也是基于 Blob,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。Blob 对象通过 Blob 构造函数来创建:
Blob(blobParts[, options])
var debug = {hello: "world"}; var blob = new Blob([JSON.stri.jpg" alt="html5的文件类型声明(浅析HTML5中的download属性使用)" border="0" />
如果需要实现一些简单的文本或 JS 字符串之类的文件下载,可以通过将文本信息转成 blob 二进制流,生成一个 Blob URL,配合 download
属性完成下载,代码如下。
const downloadText = (text, filename = '') { const a = document.createElement('a') a.download = filename const blob = new Blob([text], {type: 'text/plain'}) // text指需要下载的文本或字符串内容 a.href = window.URL.createObjectURL(blob) // 会生成一个类似blob:http://localhost:8080/d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串 document.body.appendChild(a) a.click() a.remove() }
这种 Blob URL 与常见的 HTTP URL 有什么区别呢?
Blob URL / Object URL是一种伪协议,可以让Blob和File对象用作图像和二进制数据下载链接等URL源。
浏览器在内部通过 URL.createObjectURL()
创建一个对 Blob 或 File 对象的特殊引用,生成的 Blob URL 只能在浏览器本地的单个实例和同一会话中使用,并且这个 URL 对象会在页面退出的时候被浏览器释放。
因此 Blob URL 并不能指向一个服务器资源 ,你无法在其它页面中打开它。同时由于编码格式有所差别,Blob URL 比起 Data URLs 所占的空间资源更少,性能也更好。
Blob 为 Web 开发提供了一个非常有用的功能:创建 Blob URL。将二进制数据封装为 Blob 对象,然后使用 URL.createObjectURL()
生成 Blob URL,由于Blob URL本身就是一个同源URL,可以使用该 URL 配合 download
解决跨域资源的下载以及命名问题。
解决方案
通过 Blob 和 Fetch 可以解决跨域和文件命名的问题:使用 fetch
获取跨域资源返回一个blob 对象并生成一个 Blob URL,配合 <a>
标签的 download
属性触发下载,代码如下:
function download(href, filename = '') { const a = document.createElement('a') a.download = filename a.href = href document.body.appendChild(a) a.click() a.remove() } function downloadFile(url, filename='') { fetch(url, { headers: new Headers({ Origin: location.origin, }), mode: 'cors', }) .then(res => res.blob()) .then(blob => { const blobUrl = window.URL.createObjectURL(blob) download(blobUrl, filename) window.URL.revokeObjectURL(blobUrl) }) }
此时再点击下载,可以正常的将跨域图片下载到本地了。
需注意的是跨域资源所在的服务器需要配置 Access-Control-Allow-Origin
信息,否则会得到一个大写的跨域报错。header 配置例如:
// 允许任何域名访问 header('Access-Control-Allow-Origin: *'); //指定域名访问 header('Access-Control-Allow-Origin: https://h5.ele.me');
目前这种方法还存在一些不足,例如浏览器会限制 Blob 数据大小不超过500M,在性能方面也会有所不足。
总结
目前前端有很多种下载方法, download
属性下载属于其中比较简单的一种,不过仔细考量其中的一些特性也能挖掘出很多有用的信息。 download
与浏览器特性紧密相关,目前该属性的兼容性也是一大问题,不过连微软官方都恳求用户不要再使用 IE ,相信以后 download
的兼容性问题会持续得到改善,应用前景也会越来越广阔。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。
- html5拖拽标签(Html5原生拖拽相关事件简介以及基础实现)
- h5页面强制关注微信公众号(Html5页面获取微信公众号的openid的方法)
- HTML5 <figure> 、<figcaption>标签
- html5视频播放(使用HTML5加载音频和视频的实现代码)
- HTML5 audio标签
- html5支持video的视频格式(解决html5中的video标签ios系统中无法播放使用的问题)
- html5长按动画效果(HTML5自定义元素播放焦点图动画的实现)
- ios如何播放html5(Html5移动端适配IphoneX等机型的方法)
- html5炫酷代码(HTML5超炫酷粒子效果的进度条的实现示例)
- html5如何设置标签(HTML5中在title标题标签里设置小图标的方法)
- html5实时通讯(使用Html5 Stream开发实时监控系统)
- html5带图标下拉菜单(html5小程序飞入购物车抛物线绘制运动轨迹点)
- php 处理html表单(PHP使用HTML5 FormData对象提交表单操作示例)
- html5清除浮动的方法(HTML5实现移动端点击翻牌功能)
- html5播放器按菜单键没反应(解决HTML5中的audio在手机端和微信端的不能自动播放问题)
- html5导航栏跳转(Html5跳转到APP指定页面的实现)
- 王牌部队,你看的剧情我看的时尚(你看的剧情我看的时尚)
- 被鉴定的古董价值300万 当心,你可能遇到诈骗了(被鉴定的古董价值300万)
- 英语难学吗(初中英语难学吗)
- 如何追女孩子(如何追女孩子的技巧和方法)
- 是不是快乐全被你拿走了(而是你得到的)
- 世界上只有妈妈好(世界上只有妈妈好的歌词)
热门推荐
- UML对象图的介绍
- pycharm导入turtle出现错误(解决Pycharm调用Turtle时 窗口一闪而过的问题)
- easyui datebox的用法
- vue和springboot实战项目(vue+spring boot实现校验码功能)
- sql查询语句casewhen是什么意思(SQL Server中使用判断语句IF ELSE/CASE WHEN 案例)
- vue封装组件技巧(浅谈vue中所有的封装方式总结)
- 云服务器推荐流程(云服务器入门须知的3个技巧)
- apache搭建ftp服务器(使用Apache&花生壳架设Web服务器)
- 云服务备份后怎么恢复数据(云服务器的数据被删除还能恢复吗?)
- vue 组件如何转换虚拟dom(Vue源码分析之虚拟DOM详解)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9