公司项目有导入和导出功能
后端导出接口返回的是文件流形式前端需要对文件名称以及文件流做额外处理
首先是请求部分
export function getExport(params){
return request({
url:'请求后端接口',
method:'get',
params,
responseType:'blob',//這里需要设置一下返回类型,不然文件可能会下载后可能会有问题
headers:{
groupId:10111,//这里是我们公司项目自己需要的集团ID可以忽略
}
})
}
接下来是下载方法 注意fileName這个字段
function downLoad(fileName, data) {
const filename = fileName
const blob = new Blob([data], { type: 'application/octet-stream' })
const href = window.URL.createObjectURL(blob)
// 兼容 ie
const link = document.createElement('a')
link.style.display = 'none'
link.href = href
link.download = decodeURIComponent(filename)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(link)
}
对后端的文件接口做额外处理
一般文件流的接口后端会在请求上加一个fileName是转义后的中文
具体可以参考 Content-disposition
Content-disposition
前端需要在请求拦截器处理一下這个请求
注意fileName具体还要看后端怎么约定返回的再做处理(文件后缀)
request.interceptors.response.use(
(resopnse) => {
//判断一下响应头有没有這个属性表示是不是文件流
if (Object.keys(response['headers']).includes('content-disposition')) {
const fileName = response['headers']['content-disposition']
.split(';')[1]
.split('filename=')[1];
const res = {
fileName: decodeURIComponent(fileName),
data: response.data,
};
return res;
}
return response.data;
},
(error) => {
if (axios.isCancel(error)) {
throw error.message
} else if (error.resopnse) {
let code = error.resopnse.status
switch (code) {
case 401:
remoteCookies()
window.location.href = window.location.href
break
case 502:
Message.error(error.resopnse.message || '服务器错误')
}
} else {
Message.error(error || '请求超时')
}
return Promise.reject()
}
)
处理请求
const getFile=async()=>{
//结构拿到文件名称和data文件流
let {fileName,data}=await getFileStream()
//使用之前编写好的下载函数
downLoad(fileName,data)
}
为了避免实际开发中的联调问题,前端可以自己先模拟一下
现在用node方式返回一个文件流模拟下载
首先搭建基本项目工程
npm init 初始化一个package.json文件
下载 npm install express body-parser cors 几个工具包
Content-type对照表的网址
编写本地服务器
var http = require('express')
var app = http()
var cors = require('cors')
var body = require('body-parser')
app.use(cors())
const fs = require('fs') // 引入自带fs模块读取文件操作
app.all('*',function(req,res,next){
next()
})
app.use(body.urlencoded({extended:false}))
app.use(body.json())
app.get('/file',(req,res)=>{
let fileName='./任务导入模板.xlsx'// 文件地址随意這里先写死
let name=encodeURIComponent(fileName.split('.')[1])
//设置文件流的响应头的俩种方法
//res.setHeader()
//res.writeHead()
res.writeHead(200,{
'Content-Type':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition':`attachment;filename=${name}.xlsx`,
'Access-Control-Expose-Headers':'Content-Disposition'
})
//创建可读流
let readStream=fs.createReadStream(fileName)
readStream.on('data',(chunk)=>{}) //开始读取数据
readStream.on('close',(res)=>{})//处理完成
readStream.pipe(res) // 返回文件流
})
app.listen(8080,()=>{
console.log('http://127.0.0.1:8080启动了')
})
关于node文件相关的资料可以参考
奇舞精选的一篇文章
深入了解node的文件流
先用postman测试一下请求
看下前端页面请求
请求返回的文件流
控制台打印输出以及下载文件