文件导出方法的思路
这里主要讲解blob导出的思路
1. 首先设置一个方法名,接受payload={method='get', url, param, fileName}和options={header},返回promise
function downBlob(payload: payloadType, options?: optionsType) { return new Promise(((resolve, reject) => { })); }
2. 然后,创建一个请求XMLHttpRequest,设置返回blob类型为文件流等配置参数 const { method = 'GET', url = '', param, fileName = '' } = payload;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const requrstUrl = method === 'GET' ? `${url}?${param}` : url; let name = fileName; // 获取 XMLHttpRequest const xmlResquest = new XMLHttpRequest(); // 发起请求 xmlResquest.open(method, requrstUrl, true ); // 返回类型为文件流 xmlResquest.responseType = 'blob' ; // 设置请求头类型 xmlResquest.setRequestHeader( 'Content-type' , 'application/json' );<br> // 设置header, options.headers 看情况需要,可支持 Object.entries(options.headers || {}).forEach(item => { const [k, v] = item; xmlResquest.setRequestHeader(k, v); }); |
3. 设置返回方法 onload,然后发送请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | xmlResquest.onload = (oEvent) => { // 处理下载的文件 const content = xmlResquest.response; const blob = new Blob([content]); // 请求失败 if (xmlResquest.status != 200) { message.error( '请求失败' ); return ; } // 从这个字段获取 filename const contentDisposition = xmlResquest.getResponseHeader( 'content-disposition' ); if (!name && contentDisposition) { const matched = contentDisposition.match(/filename*=(.*)/) || contentDisposition.match(/filename=(.*)/); // 获取filename的值 const filename = matched && matched[1]; name = filename ? decodeURIComponent(filename) : '' ; } // 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob if ( 'msSaveOrOpenBlob' in navigator) { navigator.msSaveOrOpenBlob(blob, name); return ; } }; if (method === 'GET' ) xmlResquest.send(); if (method === 'POST' ) xmlResquest.send(JSON.stringify(param)); |
4. 还需要兼容下ie10以下浏览器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | const reader = new FileReader(); reader.onload = (event) => { // json成功表示服务器报错,将错误信息提示出来 try { const res = JSON.parse(reader.result); message.error(res.errorMsg); reject(res); } catch (e) { // json化失败,表示是一个文件流,将文件流下载下来 // 组装a标签 const elink = document.createElement( 'a' ); // 设置下载文件名 elink.download = name || `${timestamp}.xlsx`; elink.style.display = 'none' ;<br> const blobUrl = URL.createObjectURL(blob);<br> elink.href = blobUrl; document.body.appendChild(elink); elink.click(); document.body.removeChild(elink); URL.revokeObjectURL(blobUrl); resolve( true ); } }; reader.readAsText(content); }; |
5. 总代码合并起来
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | function fileDownBlob(payload, options) { return new Promise(((resolve, reject) => { const { method = 'GET' , url = '' , param, fileName = '' } = payload; const requrstUrl = method === 'GET' ? `${url}?${param}` : url; let name = fileName; // 获取 XMLHttpRequest const xmlResquest = new XMLHttpRequest(); // 发起请求 xmlResquest.open(method, requrstUrl, true ); // 返回类型为文件流 xmlResquest.responseType = 'blob' ; // 设置请求头类型 xmlResquest.setRequestHeader( 'Content-type' , 'application/json' ); // 设置header, options.headers 看情况需要,可支持 Object.entries(options.headers || {}).forEach(item => { const [k, v] = item; xmlResquest.setRequestHeader(k, v); }) // 设置返回方法 xmlResquest.onload = (oEvent) => { // 处理下载的文件 const content = xmlResquest.response; const blob = new Blob([content]); // 请求失败 if (xmlResquest.status != 200) { message.error( '请求失败' ); return ; } // 从这个字段获取 filename const contentDisposition = xmlResquest.getResponseHeader( 'content-disposition' ); if (!name && contentDisposition) { const matched = contentDisposition.match(/filename*=(.*)/) || contentDisposition.match(/filename=(.*)/); // 获取filename的值 const filename = matched && matched[1]; name = filename ? decodeURIComponent(filename) : '' ; } // 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob if ( 'msSaveOrOpenBlob' in navigator) { navigator.msSaveOrOpenBlob(blob, name); return ; } // 下面是支持ie10以下版本 const reader = new FileReader(); reader.onload = (event) => { // json成功表示服务器报错,将错误信息提示出来 try { const res = JSON.parse(reader.result); message.error(res.errorMsg); reject(res); } catch (e) { // json化失败,表示是一个文件流,将文件流下载下来 // 组装a标签 const elink = document.createElement( 'a' ); // 设置下载文件名 elink.download = name || `${timestamp}.xlsx`; elink.style.display = 'none' ; const blobUrl = URL.createObjectURL(blob); elink.href = blobUrl; document.body.appendChild(elink); elink.click(); document.body.removeChild(elink); URL.revokeObjectURL(blobUrl); resolve( true ); } }; reader.readAsText(content); }; // 发送请求 if (method === 'POST') xmlResquest.send(JSON.stringify(param)); if (method === 'GET') xmlResquest.send(); })); } |
写到这里整个导出的方法就结束了。
这里在讲解下URL.createObjectURL和URL.revokeObjectURL
URL.createObjectURL:静态方法会创建一个DOMString、,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的document、 绑定。这个新的URL 对象表示指定的File、 对象或Blob、 对象。
URL.revokeObjectURL: 在每次调用 createObjectURL方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。
若有不对的地方,欢迎大家一起探讨深入了解~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理