之前讲了上传文件,本节我们来讨论下如何下载文件。为了方便讲解,我们使用nest g res download新建一组服务
- 第一种方式,直接在controller里调用res的download方法,简单粗暴
import { join } from 'path' @Controller('download') export class DownloadController { constructor(private readonly downloadService: DownloadService) {} @Get() getFile(@Req() req: Request, @Res() res: Response) { // 设置图片资源路径 const url = join(__dirname, '..', 'image', '1680774602139.jpg'); // 下载图片 res.download(url); } }
res.download接收一个URL,指向服务器中资源的地址。此时在前端访问localhost/download即可直接下载文件
- 以字节流的方式传输
本例中我们使用zip压缩一下,借助compressing模块实现
import { join } from 'path'; import { zip } from 'compressing'; @Get('stream') async getFileStream(@Req() req: Request, @Res() res: Response) { // 设置图片路径 const url = join(__dirname, '..', 'image', '1680778329068.jpg'); // 通过zip.Stream创建一个压缩文件流 const tarStream = new zip.Stream(); // 将图片资源加入流中 await tarStream.addEntry(url); // 设置请求头信息,字节流对应的MIME类型为application/octet-stream res.setHeader('Content-Type', 'application/octet-stream'); // 固定格式,提示浏览器打开文件下载对话框,filename即是对话框中文件的名字 res.setHeader('Content-Disposition', `attachment;filename=xiaoman`); // 用管道连接文件流和响应流 tarStream.pipe(res) }
启动服务,此时我们在浏览器中访问localhost/download/stream时浏览器就会自动下载二进制格式的文件,但是下载的文件并不能直接打开,需要在前端进行解析
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <button>下载</button> </body> <script> let btn = document.querySelector('button') btn.onclick = async () => { url = 'http://localhost:3000/download/stream' // 请求url,将返回的内容设置为arrayBuffer const response = await fetch(url).then((res) => res.arrayBuffer()) // 使用arrayBuffer创建一个blob let blob = new Blob([response]) // 生成指向blob的唯一URL地址 let Url = URL.createObjectURL(blob) // 创建a标签并点击下载 let a = document.createElement('a') a.href = Url a.download = '小满.zip' a.click() } </script> </html>
以上,下载的文件会被保存成"小满.zip"