vue项目,有两种方式实现请求接口返回文件流并进行下载:
第一种:使用a标签的特性,使用链接实现
第二种:下载文件流的方式
一。前端实现静态文件的下载
1.将要下载的静态文件放入项目的public文件夹中,如下图,test.pptx文件
2.代码中添加a标签:
<a href="..//test.pptx" style="color: #FF0000; text-decoration: underline" >下载</a>
3.打包之后test.pptx文件就会放在打包文件dist中,如下图:
二。当接口为get请求时,可以使用a标签实现动态文件的下载
这里使用的是前后端合作的方式
下载动态文件流就是文件存储在后台,需要使用接口请求,来实现文件的下载
1.配置项目的Base url
const URL_GLOBAL = {
development: "http://localhost",
production: "https://baidu.com",
developmentPort: ":8888/hhh",
productionPort: "/abc",
}
this.globalURL = URL_GLOBAL[process.env.NODE_ENV] + URL_GLOBAL[process.env.NODE_ENV + 'Port'];
2.当接口为get请求时,可以使用a标签,将接口拼接在href中,如果有参数可以直接拼接在url后面
<a
:href="globalURL +'/download/downloadexcel?type=code"
>Download Excel
</a>
3.点击页面中a标签的按钮,就可以将文件下载到本地了
三。当接口为post请求时,就不能使用a标签了,使用下载文件流的方式实现
1.配置项目的Base url
const URL_GLOBAL = {
development: "http://localhost",
production: "https://baidu.com",
developmentPort: ":8888/hhh",
productionPort: "/abc",
}
this.globalURL = URL_GLOBAL[process.env.NODE_ENV] + URL_GLOBAL[process.env.NODE_ENV + 'Port'];
2.使用按钮触发下载
<el-button type="primary" @click="exportExcel">Download Excel</el-button>
3.引入axios
import axios from "axios";
4.实现接口请求,下载文件流
注意必坑:
当获取后端设置的响应头字段时,比如设置的文件名称或者自定义的参数时,
要在后端设置响应头,必须要设置以下代码,来公开自定义响应头,否则前端拿不到响应头中对应的数据:
response.setHeader("Access-Control-Expose-Headers","content-disposition");
exportExcel() {
let params = {
type: 'code'
}
//下载文件流
let url = this.globalURL + '/code/getcode'
axios.post(url,params,{
responseType:'blob'
}).then(res => {
const name = res.headers['content-disposition'];
let fileName = '';
if (name) {
const str1 = name.replace(' ', '');
const arr1 = str1.split(';');
arr1.some(item => {
if (item.indexOf('filename') != -1) {
fileName = item.split('=')[1];
}
return item.indexOf('filename') != -1;
});
if (fileName === ''){
fileName = 'excel.xlsx'
}
} else {
fileName = 'excel.xlsx'
}
try {
let objectUrl1 = window.URL.createObjectURL(new Blob([res.data]));
let elink = document.createElement('a');
elink.setAttribute('download', decodeURI(decodeURI(fileName)));
elink.style.display = 'none';
elink.href = objectUrl1;
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
window.URL.revokeObjectURL(elink.href);
}catch (err){
this.$message.warning('download error!')
}
})
},
四.如果想要下载的接口request配置headers,a标签就不能满足需求了,需要使用下载文件流的方式实现
这种方式,不管接口是get请求,还是post请求都可以用
1.配置request.js文件,封装axios
const service = axios.create({
baseURL: URL_GLOBAL[process.env.NODE_ENV] + URL_GLOBAL[process.env.NODE_ENV +'Port'],
timeout: 300000,
});
配置请求头,将需要的信息存储在请求头中
service.interceptors.request.use(
async (config)=>{
if (process.env.NODE_ENV !== 'development'){
config.headers['username'] = 'annie'
}
return config
},
error => {
Promise.reject(error)
}
)
2.在vue文件中,引入封装好的axios
import fetch from "../request"
使用按钮触发下载事件
<el-button type="primary" @click="downloadFiles">Download excel</el-button>
3.实现接口请求,下载文件流
注意必坑:
当获取后端设置的响应头字段时,比如设置的文件名称或者自定义的参数时,
要在后端设置响应头,必须要设置以下代码,来公开自定义响应头,否则前端拿不到响应头中对应的数据:
response.setHeader("Access-Control-Expose-Headers","fileName");
详细了解Access-Control-Expose-Headers:Access-Control-Expose-Headers 响应报头、跨域 公开响应头_withexposedheaders-CSDN博客
接口请求
downloadFiles() {
return new Promise((resolve, reject) => {
fetch({
url: "/down/download",
method: "get",
params: {
id: '222',
},
responseType: "blob",
})
.then((res) => {
// 获取后端设置的响应头字段时,比如设置的文件名称或者自定义的参数时,
// 在后端设置响应头时,必须要设置以下代码,来公开自定义响应头,否则前端拿不到:
// response.setHeader("Access-Control-Expose-Headers","fileName");
const fileName = res.headers["filename"];
const blob1 = res.data;
console.log(blob1)
console.log(fileName)
if ("download" in document.createElement("a")) {
const elink = document.createElement("a");
elink.download = decodeURIComponent(fileName);
elink.style.display = "none";
elink.href = URL.createObjectURL(blob1);
document.body.appendChild(elink);
elink.click();
console.log(elink)
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
} else {
// IE10+下载
navigator.msSaveBlob(blob1, fileName);
}
})
.catch((err) => {
reject(err);
});
});
},