如何实现一个下载功能呢?其实最简单的方式就是用get请求,指向后台的一个资源即可,不过有的情况下,我们需要传输的参数过多,无法使用get,那使用post又该如何实现呢?今天我们就来系统理一下。
get方式
get方式比较简单,直接上代码:
import { Controller, Get, Req, Res } from "@nestjs/common";
const fs = require('fs');
const path = require('path');
@Controller("file")
export class FileController {
constructor() { }
@Get('/download')
async download(@Req() req, @Res() res) {
let filepath = `D:/test.zip`;
res.setHeader('ContentType', 'application/octet-stream');
let filename = `test.zip`;
res.setHeader('Content-Disposition', `attachment;filename=` + encodeURIComponent(filename));
fs.createReadStream(filepath).pipe(res);
}
}
get请求上可以带上userid和filename等信息,后端根据这些参数定位到文件所在的路径,然后将文件流通过stream管道输出即可。
window.open('http://localhost:3000/file/download?userid=xxx&filename=test')
post方式
如果我们改成post请求:
import { Controller, Get,Post, Req, Res } from "@nestjs/common";
const fs = require('fs');
const path = require('path');
@Controller("file")
export class FileController {
constructor() { }
@Post('/download')
async download(@Req() req, @Res() res) {
let filepath = `D:/test.zip`;
res.setHeader('ContentType', 'application/octet-stream');
let filename = `test.zip`;
res.setHeader('Content-Disposition', `attachment;filename=` + encodeURIComponent(filename));
fs.createReadStream(filepath).pipe(res);
}
}
然后前端可以这样访问吗:
axios.post('/api/file/download',{}).then(result=>{ //代理
let res = result.data;//后端直接返回流
window.open(res);
});
这样做很明显是不行的,我们可以改变一下策略,把请求拆分为两步。
1、发起post请求,当文件处理完毕后,返回给前端文件相关信息,如果是处理大文件时间较长的话,就设置永不超时。
2、发起get请求,根据post返回的信息,定位到资源的存放路径,用window.open指向一下即可。
后端:
import { Controller, Get,Post, Req, Res } from "@nestjs/common";
const fs = require('fs');
const path = require('path');
@Controller("file")
export class FileController {
constructor() { }
@Post('/zip')
handleZip(@Req() req, @Res() res) {
console.log('开始处理>>>');
res.connection.setTimeout(0);//永不超时
console.log('处理中...');
fs.copyFileSync('D:/test.zip','D:/zip/123456/test.zip');//拷贝文件,src dest
setTimeout(() => {
res.json({ //返回文件信息
code: 200,
data:{
filename:'test.zip',
userid:'123456'
}
});
console.log('处理完毕');
}, 3000);
}
@Get('/download')
async download(@Req() req, @Res() res) {
let filename = decodeURIComponent(req.query.filename);
let userid = req.query.userid;
let zipPath = path.resolve('D:/', 'zip',userid, filename);
if(filename && fs.existsSync(zipPath)) {
res.setHeader('ContentType', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment;filename=` + encodeURIComponent(filename));
fs.createReadStream(zipPath).pipe(res);
}
}
}
前端:
axios.post('/api/file/zip',{}).then(result=>{ //代理
let res = result.data;//返回的json
if(res && res['code'] === 200) {
window.open(`http://localhost:3000/file/download?userid=${res.data.userid}&filename=${encodeURIComponent(res.data.filename)}`);
}
});
网友评论