前端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); } }); }); }; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南