前端js实现下载文件

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

1.简单快速

1
2
3
4
5
6
7
8
9
10
11
12
13
axios(url,{<br> method:'post',<br> data: 'data',<br> 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,方便进行请求前的配置后返回后的数据处理,下面是一个简单的例子,你可以参考此方法整合进你自己的项目,把错误处理和下载文件在接口上统一处理,调用的地方就不用每次都重写一遍下载方法了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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 @   anin  阅读(1915)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示