大部分文件下载都是在服务器放置好需要下载的资源,然后由服务器配置可以下载的文件类型,由系统去判断权限。如果文件比较小,不想通过系统去判断权限给出下载地址,如何在前端完成下载功能呢?
只需要将数据准备好,然后调用以下js函数即可:
调用方式:downLoadFile('test.txt', "Hello world!");
以上文档 转自:pakinguo(http://blog.csdn.net/dragon_q/article/details/46970699)
由于我的工作重心转向网盘的开发和维护,最近整了一个html版的文件浏览器demo,核心内容为上传和下载,积累了一点经验,这里把其中下载的内容拿出来谈一谈。(本文涉及的前端使用vue.js,后台使用node.js+express)
一个文件的下载
-下载链接
开始之前,回想起我们平时上网下载文件接触到的链接,都是譬如
http://xxxxxx/name=cccc.rar
http://xxxxxx/download/abcabc.exe
等这种类型的链接。
观察后不难发现这些都是get形式的链接。事实上如果用post,后台会在xhr的responseText中返回文件内容,无法保存到本地,不过可以直接append到页面上,然后让用户自己复制。综合以上考虑,因此我们需要用get建立传输的链接。
-从打开开始
首先,我们根据需要的参数,拼出需要的get链接。要下载一个文件,需要传入它的文件地址和文件名,get链接就可以这么设计:
- 1
- 1
其中有两个参数:dir,name
后台中根据这两个参数拿到对应的文件,用node.js里fs流的方式传出来:
- 1
- 2
- 3
- 1
- 2
- 3
这样下载下来的文件,文件名是混乱的,应该在报文里传入Content-Disposition告诉浏览器文件名(Content-type可以不设置):
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
当然下载前应该判断下是否存在这个文件,最后后台的代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
建立好后台之后,前端直接拿链接去测试。浏览器上打开(具体链接自己配置)
http://localhost:2333/downloadSingle?dir=f%3A%5Cdemo&name=desktop.ini
小文件在浏览上冒出来了,下载成功。
-无“闪现”下载
你问怎么用代码下载下来?最简单的方法就是把这个链接放进window.open(url)
里面,然后浏览器会新开个页面,建立链接后会关闭访问页,开始下载。然而,这种方法会闪一下,体验起来比较挫。接下来介绍一种没有”闪现”的方法。
我在《ie8下用iframe解决表单submit以及二级域名跨域的方法》中介绍过如何使用iframe来避免submit提交后页面的自动跳转(使用iframe屏蔽submit提交表单后的自动跳转),基本原理就是隐藏一个iframe,随浏览器怎么折腾它的死活,反正我们看不到就行了。
下面贴代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
需要下载文件时,调用downloadByIframe(url)
即可。
不过这样的方法有个缺点,当后台找不到文件的时候,无法返回错误信息,不知道的还以为挂掉了。如果要即时相应的话,同样可以参考我这篇文章介绍的方法:使用onload获取后台返回在iframe中的数据
多个文件的下载
以上介绍了下载一个文件时的处理方法。当然很可能会遇到多个文件要下载的情况。
遇到多个文件要下载时,如果直接使用单个文件下载的方法,可以使用for循环,然后往里面扔downloadByIframe(url)
,简单暴力。
不过文件越多越容易引起强迫症,而且对于文件夹而言,无法使用这种方式下载。
现在很多网盘对待多文件下载的情况时,会先把它们全部压缩起来,打包成一个文件再下载。通过这种思路,我们可以先在服务器端压缩文件,存到本地,然后通过这个压缩文件的路径和名称,拼出get的链接,再使用上文介绍的下载单个文件方法,即可顺利下载。使用这种思路,文件夹同样也可以打包进来。
-archiver压缩模块
在开始之前,首先要介绍下在本文node.js中使用的压缩模块archiver,npm可以下载到。我是通过《 nodejs 中压缩/解压方案》(倪舒扬)这篇文章了解到archiver的,该篇文章比较详细的讨论了node.js其他几个压缩模块的利弊,有兴趣可以阅读一下。
先贴代码:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
其中,archive.append只能放入单个文件,如果要放入文件夹或多个文件,需要使用archive.bulk()
这个方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
官方文档对这个方法有更多的介绍archive.bulk传送门,有兴趣的可以啃一下。
archiver还提供了几个监听事件,用于处理阶段性的事件:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
-代码设计
前端代码比较简单,直接贴出来(为省事我用的vue.js,大家可以用jQuery或者XMLHttpRequest自己写一个):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
后台综合上面的archiver,代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
其中需要强调的一点是,archiver的bulk中src传入的文件夹和文件写法不同,可以参考如下格式:
- 1
- 2
- 1
- 2
锦上添花
-统一下载接口
后台download这个接口经过改造,可以一起适配单个文件和多个文件下载的情况。
通过判断fileNameArray中是否为单个文件,可以建立一个分支:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这样前端不管用户选择了几个文件,只需要post download这个接口,拿到返回的链接塞进downloadByIframe()
这个方法即可。
至此,本文文件下载的方法全部介绍完毕。
以上node.js的文档转自:Lienviws(http://blog.csdn.net/liyijun4114/article/details/51743068#t1)