Bootstrap

文件流下载文件后提示不支持打开该类型文件或文件已损坏

在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的就可以了

;