如何用 JavaScript 下载文件
简介
我们知道,下载文件是一个非常常见的需求,但由于浏览器的安全策略的限制,我们通常只能通过一个额外的页面,访问某个文件的 url 来实现下载功能,但是这种用户体验非常不好。
幸好,HTML 5 里面为 <a> 标签添加了一个 download 的属性,我们可以轻易的利用它来实现下载功能,再也不需要用以前的笨办法了。
原理
我们先看看 download 的使用方法:
<a href="http://somehost/somefile.zip" download="filename.zip">Download file</a>
看看上面的代码,只要为 <a> 标签添加 download 属性,我们点击这个链接的时候就会自动下载文件了~
顺便说下,download 的属性值是可选的,它用来指定下载文件的文件名。像上面的例子中,我们下载到本地的文件名就会是 filename.zip 拉,如果不指定的话,它就会是 somefile.zip 这个名字拉!
事实上,用 JavaScript 来下载文件也是利用这一特性来实现的,我们的 JavaScript 代码不外乎就是:
用 JavaScript 创建一个隐藏的 <a> 标签
设置它的 href 属性
设置它的 download 属性
用 JavaScript 来触发这个它的 click 事件
翻译成 JavaScript 代码就是:
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
var filename = 'what-you-want.txt';
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
好拉,是不是看到有个陌生的东东呢?
window.URL
window.URL 里面有两个方法:
createObjectURL 用 blob 对象来创建一个 object URL(它是一个 DOMString),我们可以用这个 object URL 来表示某个 blob 对象,这个 object URL 可以用在 href 和 src 之类的属性上。
revokeObjectURL 释放由 createObjectURL 创建的 object URL,当该 object URL 不需要的时候,我们要主动调用这个方法来获取最佳性能和内存使用。
知道了这两个方法之后,我们再回去看看上面的例子就很容易理解了吧!只是用 blob 对象来创建一条 URL,然后让 <a> 标签引用该 URL,然后触发个点击事件,就可以下载文件了!
那么问题来了,blob 对象哪里来?
Blob 对象
Blob 全称是 Binary large object,它表示一个类文件对象,可以用它来表示一个文件。根据 MDN 上面的说法,File API 也是基于 blob 来实现的。
由于本文的主题是讲 JavaScript 下载文件,那我们构建 blob 的方式就是通过服务器返回的文件来创建 blob 拉!
而最简单的方式就是用 fetch API 了,我们可以整合上面的例子:
fetch('http://somehost/somefile.zip').then(res => res.blob().then(blob => {
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
var filename = 'myfile.zip';
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
很简单对吧!
你可能会问,何必这么麻烦呢?直接写成下面这样不就好了:
<a href="http://somehost/somefile.zip" download="myfile.zip">Download file</a>
嗯,对于这种写法,我只能说,你做的太正确了!如果你要下载的是已经存在服务器上面的静态文件的话,那么写成这样是最方便的。
为什么要用 JavaScript 下载文件
好拉,说了半天,其实我们一直说的都是:「不要用 JavaScript 下载文件拉,限制多多,又不好用,直接用 html 就好拉,简单方便又快捷」这个论调。
事实上也确实如此,但有些时候我们确实需要通过 JavaScript 来做一些预处理。
权限校验
有些时候,我们需要对下载做一些限制,最常见的就是权限校验了,如检查该用户是否有下载的权限,是否有高速下载的权限等等。这时候,我们可以利用 JavaScript 做一些预处理。如:
fetch('http://somehost/check-permission', options).then(res => {
if (res.code === 0) {
var a = document.createElement('a');
var url = res.data.url;
var filename = 'myfile.zip';
a.href = url;
a.download = filename;
a.click();
} else {
alert('You have no permission to download the file!');
}
});
在这个例子里面,我们没有用 blob 来构建 URL,而是通过后端服务器来计算出用户的下载链接,然后再利用之前提到的动态创建 <a> 标签的方式来实现下载,很简单吧!
转自:[前端早读课]http://mp.weixin.qq.com/s/U_LuC2Nyv4ZcNpX0tHDP3g
如何用 JavaScript 下载文件的更多相关文章
- 如何用ajax下载文件
引子 在HTML5没来之前,浏览器想要下载文件,可能有这么几种方式: 借助a标签,<a href="学习资料.xlsx"></a> window.locat ...
- 【Javascript下载文件的Post实现】
/** *从服务器上下载数据 *@param paras Json格式的键值对参数 */ downLoadFromServer: function (paras) { //init a new win ...
- Android技巧分享——如何用电脑下载在Google play中应用的apk文件
[Android技巧分享系列] 1.Android技巧分享——让官方模拟器和genymotion虚拟机飞起来 2.Android技巧分享——如何用电脑下载在Google play中应用的apk文件 G ...
- 使用JavaScript下载csv文件
前端可以使用JavaScript在客户端下载包含页面数据的文件,这里以下载CSV格式文件为例,代码如下: function downloadData(data, filename, type) { v ...
- [转] 使用 JavaScript 创建并下载文件
[From] https://gaohaoyang.github.io/2016/11/22/js-create-file-and-download/ 本文将介绍如何使用 JavaScript 创建文 ...
- 使用 JavaScript 创建并下载文件
先上代码 Blob 对象 Blob URLs 模拟 click 小结 参考 本文将介绍如何使用 JavaScript 创建文件,并自动/手动将文件下载.这在导出原始数据时会比较方便. 先上代码 /** ...
- [转]用JavaScript在浏览器中创建下载文件
前端很多项目中,都有文件下载的需求,特别是JS生成文件内容,然后让浏览器执行下载操作(例如在线图片编辑.在线代码编辑.iPresst等. 但受限于浏览器,很多情况下我们都只能给出个链接,让用户点击打开 ...
- ajax请求过程中下载文件在火狐下的兼容问题
项目中碰到的问题,记录如下. 需求很简单,点击一个文件链接下载该文件,同时向后台发送请求.需求很常见,用户点击下载后通常要进行下载量的统计,统计的话可以利用 script标签 或者 img标签(图片p ...
- PHP中使用Session配合Javascript实现文件上传进度条功能
Web应用中常需要提供文件上传的功能.典型的场景包括用户头像上传.相册图片上传等.当需要上传的文件比较大的时候,提供一个显示上传进度的进度条就很有必要了. 在PHP .4以前,实现这样的进度条并不容易 ...
随机推荐
- Nginx工作原理
Nginx的模块 Nginx由内核和模块组成. Nginx的模块从结构上分为核心模块.基础模块和第三方模块: 核心模块:HTTP模块.EVENT模块和MAIL模块 基础模块:HTTP Access模块 ...
- Windows环境下安装配置Teamcity配合git自动发布mvc,webapi站点
以下是本人配置Teamcity具体环境和步骤,只实现了项目发布,打包.Nodejs npm gulp没有配置成功,后期补上. 1 环境安装 本人使用的是windows7 sp1 64位系统,(.net ...
- java中浅层克隆和深层克隆
1.浅复制与深复制概念 浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象 ...
- 更新几篇之前写在公众号上的文章:线性可分时SVM理论推导;关联分析做捆绑销售和推荐;分词、去停用词和画词云
适合阅读人群:有一定的数学基础. 这几篇文章是16年写的,之前发布在个人公众号上,公众号现已弃用.回过头来再看这几篇文章,发现写的过于稚嫩,思考也不全面,这说明我又进步了,但还是作为学习笔记记在这里了 ...
- angular、vue使用感受
最近开始学习并使用vue.js,并使用vue+node开发了一个移动端APP来练手,下面想聊聊我对于vue的粗浅看法,并将它和angular进行一些对比: 1.vue是一个轻量.高效的前端组件化框架, ...
- 规范 : angular ui router path & params
在seo文章中提到url的path 必须是 why-us,而不是whyUS 所以定了规范,所有的path 必须why-us path ?后尾的是用来filter的,所以可以WhyUs 如果是不需要给s ...
- C# Redis之ServiceStack
前面几篇博客基本把redis基本操作学习了下,但一些高级应用并没有写进博客,例如持久化.虚拟内存等,像这些主要是通过配置文件来解决的,运维方向可能更侧重一些,对于开发者来说,可能就想知道怎么用C#来和 ...
- HTML文档中使用JavaScript和css
HTML文档中使用JavaScript和css 引入css 内嵌式引入:将css代码写在HTML中的style标签里面 <!DOCTYPE html> <html> <h ...
- String和intern()浅析
String a = new String("aa"),代表在堆内存中,创建了一个字符串对象,变量a指向该对象,而该对象又指向在常量池中的字符串常量.而String a = &qu ...
- Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动
之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,我用的是默认的Tomcat. private void cr ...