在react项目中用到下载,请求后端接口返回文件流,前端来处理文件流生成文件后下载。
要设置responseType!!
采用的方法就是百度上随便一搜就可以搜到的Blob方法,最开始要下载的文件格式为.pdf,但是下载完的文件用office和WPS都打不开,先说怎么解决的这个问题,之前在百度的时候也看到有人说设置responseType就可以了,但是不信邪,就不设置,结果还真的是因为responseType,设置之后下载完的文件就都可以打开啦!
解决思路:
1、先让后端把文件流传的文件变成一个空白文档,首先可以确定的是下载没问题,可以下载下来文件,并且空白的文件是可以用Office打开的,文件流应该也没问题
2、用模拟请求的工具尝试了一下,下载的文件也可以正常打开,那么文件流一定没问题,问题应该就出在前端了
3、后端提供了其他项目下载的方法,使用的是layUI框架的,代码如下
//文件下载
function downLoadFile(ids, name) {
//创建下载请求
var oReq = new XMLHttpRequest();
//url参数为拿后台数据的接口
oReq.open("POST", '请求的下载地址', true);
oReq.responseType = "blob"; //设置responseType
oReq.onload = function (oEvent) {
var content = oReq.response;
var elink = document.createElement('a');
//name为后台返给前端的文件名,后缀名必须加,后台有返回后缀就不用管,不然下载在本地不好打开。
elink.download = name + ".xlsx";
elink.style.display = 'none';
var blob = new Blob([content], {type: "application/x-www-form-urlencoded"});
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
oReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//这个相对来说都不是很重要
//请求头里放入用户口令,必须在.open()和.send()之间设置
oReq.setRequestHeader('Blade-Auth', '设置balde-auth');
oReq.send('可以设置需要的参数');
}
我写的代码如下
//请求完接口后调用该方法 将文件流data和其他需要的数据参数传过来
saveData(data, filename) {
let blob = new Blob([data], { type: 'application/x-www-form-urlencoded' });
let blobUrl = window.URL.createObjectURL(blob);
const aElement = document.createElement('a');
document.body.appendChild(aElement);
aElement.style.display = 'none';
aElement.href = blobUrl;
aElement.download = filename;
aElement.click();
document.body.removeChild(aElement);
}
看起来代码就是一样的嘛,只不过我的接口请求是axios封装后的,balde-auth也在封装部分设置好了,看来看去只有一处不同,那就是没有设置responseType,我甚至还试了一下没用封装的接口请求,直接就用最上面的代码也是好使的,那就是responseType的问题了,在axios封装里面加上了responseType就可以了。
/**
* 设置请求拦截器,添加token
*/
axios.interceptors.request.use(
config => {
if (config.method === 'post') {
if(config.url.includes(url.common.filedownload)){
config.responseType = 'blob'; //请求加上responseType
}
}
return config
},
error => {
message.error('请求出错' + error);
return Promise.reject(error);
}
)
告诉请求前端想要的是blob的就可以了