1.0 前言

文件下载这个功能在日常开发过程中会经常用到,这里我们一起学习 在 Koa 中如何做文件下载。

2.0 源码实现文件下载

本质上浏览器下载是把文件流放到 body 中,然后修改 Content-disposition 请求头,源代码如下:

  1. // router.js
  2. router.get('/download/:name', async (ctx) => {
  3. const name = ctx.params.name
  4. const filePath = path.resolve(process.cwd(), `static/upload/${name}`) // 获取文件目录
  5. ctx.set('Content-disposition', 'attachment;filename='+name)
  6. ctx.body = fs.createReadStream(filePath)
  7. ctx.attachment(filePath)
  8. })

现在我们在 static/upload 这个目录下,放了一个 222.png 的图片,启动项目,浏览器访问 http://localhost:300/222.png ,就会触发浏览器的下载。
大家可以看到,几行代码就实现了下载功能,那这么常见的功能,社区肯定也有对应的中间件,最常用的 就是 koa-send,接下里我们讲讲 koa-send 的使用

3.0 koa-send

3.0.1 安装

  1. npm i koa-send --save

3.0.2 文件下载

  1. // router.js
  2. const send = require('koa-send')
  3. router.post('/download/:name', async (ctx){
  4. const name = ctx.params.name
  5. const path = `static/upload/${name}`
  6. ctx.attachment(path)
  7. await send(ctx, path)
  8. })

这样访问 http://localhost:300/222.png 也会触发下载,这个中间件用起来还是非常简单的。

4.0 批量下载

有时候我们文件比较多,比如,图片太多,希望打包后下载。

archiver 是一个在 Node.js 中能跨平台实现打包功能的模块,支持 zip 和 tar 格式。

  1. router.get('/downloadAll', async (ctx) => {
  2. // 将要打包的文件列表
  3. const zipName = '1.zip'
  4. const zipStream = fs.createWriteStream('1.zip')
  5. const zip = archiver('zip')
  6. zip.pipe(zipStream)
  7. zip.directory('static/upload/', false) // 添加整个文件夹到压缩包
  8. await zip.finalize()
  9. ctx.attachment(zipName)
  10. await send(ctx, zipName)
  11. })

浏览器访问 http://localhost:3000/1.zip ,会把 upload 目录下的文件打包下载

5.0 小结

这节我们一起学习在 Koa 中文件下载的几种方式,大家可以对着Demo 跑起来,看看效果 Demo 地址