前端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); } }); }); };