前端js实现下载文件

下载文件核心方法就是获取到文件流后,使用createObjectURL创建url再模拟标签点击下载

1.简单快速

axios(url,{
method:'post',
data: 'data',
responseType: 'blob', }).then((res) => { const Url = res.headers['content-disposition']; const fileName = Url?.split(';')[1].split('filename=')[1] || '文件'; const blob = new Blob([res.data]); const blobUrl = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.download = fileName; a.style.display = 'none'; a.href = blobUrl; a.click(); document.body.removeChild(a); });

 这种方式简单快速,但是需要后端能正确返回文件流,实际项目中会有网络错误,入参错误,权限控制等各种原因导致会返回不同的结果,需要进行处理

2.每次调用单独处理错误

axios(url, {
    method: 'post',
    data: 'data',
    responseType: 'blob',
}).then(res => {
    if (res.headers['content-type'].includes('json')) {
        // 正常应该返回文件流,content-type为json的时候,说明下载出错了,但是请求的时候设置了 responseType: 'blob',
        // 不能按照普通的请求方式处理返回的数据,需要转化一下
        // const text = await (new Response(res)).text();  考虑到兼容性暂不使用此API

        const reader = new FileReader();
        reader.readAsText(res.data);
        reader.onload = (readRes: any) => {
            const result = JSON.parse(readRes.target.result);
            //     message.error(result?.message);
        };

    } else {
        const Url = res.headers['content-disposition'];
        const fileName = Url?.split(';')[1].split('filename=')[1] || '文件';
        const blob = new Blob([res.data]);
        const blobUrl = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.download = fileName;
        a.style.display = 'none';
        a.href = blobUrl;
        a.click();
        a.parentNode?.removeChild(a);
        // message.success(`下载完成`);
    }
})
    .catch(err => {
        console.log('%c [ err ]', 'font-size:13px; background:pink; color:#bf2c9f;', err);
        message.error('下载失败,请稍候重试');
    });

 

 3.在实际项目中调用接口都有统一的api,方便进行请求前的配置后返回后的数据处理,下面是一个简单的例子,你可以参考此方法整合进你自己的项目,把错误处理和下载文件在接口上统一处理,调用的地方就不用每次都重写一遍下载方法了

export const downloadApi = (url: string, data: any, method: Method = 'POST') => {
    return new Promise((resolve, reject) => {
        ajax(hostUrl + url, {
            method,
            data: data,
            responseType: 'blob',
        })
            .then(res => {
                if (res.status === 200 && res.headers['content-type'].includes('json')) {
                    return Promise.reject(res);
                }
                const Url = res.headers['content-disposition'];
                const fileName = Url.split(';')[1].split('filename=')[1];
                const blobUrl = window.URL.createObjectURL(res.data);
                const aElement = document.createElement('a');
                document.body.appendChild(aElement);
                aElement.style.display = 'none';
                aElement.href = blobUrl;
                aElement.download = decodeURI((/\S*/.exec(fileName))[0]);
                aElement.click();
                document.body.removeChild(aElement);
                resolve('SUCESS');
            })
            .catch((err: any) => {
                let headers = err?.headers;
                let data = err?.data;
                if (err && err.isAxiosError && err.response) {
                    headers = err.response.headers;
                    data = err.response.data;
                }
                if (headers?.['content-type'].includes('json')) {
                    const reader = new FileReader();
                    reader.readAsText(data);
                    reader.onload = (readRes: any) => {
                        const result = JSON.parse(readRes.target.result);
                        // Toast.error(result?.msg);
                        reject(result);
                    };
                } else {
                    reject(err);
                }
            });
    });
};

 

 
posted @ 2023-05-10 17:17  anin  阅读(1845)  评论(0编辑  收藏  举报