如何用 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以前,实现这样的进度条并不容易 ...
随机推荐
- asyncio
一.简介 asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接获取一个EventLoop的引用, ...
- C# 总结const、 readonly、 static三者区别:
总结const. readonly. static三者区别: (有人问我,看似简单,我也没能立刻回答出来,总结一下,分享一下.) const:静态常量,也称编译时常量(compile-time con ...
- lazy ideas in programming
lazy形容词,懒惰的,毫无疑问是一个贬义词.但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算.本文的目的是抛砖引玉,总结一些编程中的laz ...
- APC注入
0X01 注入原理 当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的 具体的流程: 1 当EXE里的某个线程执行到sleepEX(),或者waitF ...
- BZOJ 3410: [Usaco2009 Dec]Selfish Grazing 自私的食草者(贪心)
这= =,就是线段覆盖对了= =直接贪心就行了= = CODE: #include<cstdio>#include<iostream>#include<cstring&g ...
- wpf的无边框窗体透明
本人做了3年的winform,来了新的工作,需要使用wpf.对于wpf,本人小白一个.说的不对的地方,请大家多多指导.... 今天先从wpf的窗体属性开始说起! 需要做的项目功能大概和电脑桌面类似,需 ...
- Java第三天
0.注释: 目的:方便其他人阅读理解我们的代码 三种: // 单行注释,进行解释 /**/ 多行注释 /***/ 多行注释 (/***/注释通常用于方法,函数注释,在调用写好的方法或是函数时可以通过点 ...
- 四十年前的 6502 CPU 指令翻译成 JS 代码会是怎样
去年折腾的一个东西,之前 blog 里也写过,不过那时边琢磨边写,所以比较杂乱,现在简单完整地讲解一下. 前言 当时看到一本虚拟机相关的书,正好又在想 JS 混淆相关的事,无意中冒出个问题:能不能把某 ...
- 关于margin
----W3School -----margin CSS 边距属性定义元素周围的空间.通过使用单独的属性,可以对上.右.下.左的外边距进行设置.也可以使用简写的外边距属性同时改变所有的外边距. 这个简 ...
- 2017-3-2 C#链接数据库实现登陆
只是链接一个数据库就有好多的知识:) 实际操作下来,主要是两种登陆方式: 1.Windows的身份验证: 2.Sql Sever的身份验证: 两种的方法不同,但是主要是通过复制创建数据库的字符串来链接 ...