背景
再现在正在进行的项目中,由于后端涉及到网关安全控制(我也不是太懂,毕竟不是专业),我的后端搭档没有找到好的提供静态文件服务的方式,只好以流的方式向前端写入,在前端进行如下操作:
- 前端接收blob
- 使用URL.createObjectURL() 或者 FileReader 创建下载url
- 使用a标签 href, download click() 来进行下载
但是这种方式是有缺点的
- 对于开发者来说,需要配合xhr方法来编写,增加代码量
- 只有拿到所有的二进制字节数才能进行转化url,在浏览器上才有可能看见文件已被下载
- 不支持断点续传,只能重新进行下载
对于小文件这种方式其实没有影响, 因为时间会很短,对于很大的文件来说这种方式就不可接受了,因为接收二进制字节的时间是不可控的,如果非常大的文件,在接收二进制的过程中,页面是完全无反馈的,这对于用户体验是不可接受的
流方式的文件下载
另外一套方案就是,在后端以方法文件流的方式向前端输出文件也是可以直接下载的
原理就是设置请求头
- res.setHeader(‘Content-Type’, ‘application/zip’) // 设置下载文件的mime类型
- res.setHeader(‘Content-Length’, 38282773) // 这个对于小文件可以不进行设置,不影响下载,对于大文件一定要设置文件大小,否则有可能下载坏的文件
- res.setHeader(‘Content-Disposition’, “attachment; filename=1.zip”) 在常规的 HTTP 应答中,Content-Disposition 响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。
以node.js为例
const path = require('path')
const fs = require('fs')
const http = require('http')
const server = http.createServer((req, res) => {
console.log('请求来了')
res.setHeader('Content-Type', 'application/zip')
res.setHeader('Content-Length', 38282773)
res.setHeader('Content-Disposition', "attachment; filename=1.zip")
fs.createReadStream(path.resolve('1.![在这里插入图片描述](https://img-blog.csdnimg.cn/20210624004007725.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NoZW5wYXBh,size_16,color_FFFFFF,t_70)
zip')).pipe(res)
})
server.listen(3000)
文件会被直接下载,会在浏览器上显示进度条,用户的反馈问题便被解决了,断点续传也解决了,如果安装了迅雷等下载软件,会被拉取到迅雷中进行下载。
chrome
edge