侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Vue+axios+WebApi+NPOI导出Excel文件实例方法

前端  /  管理员 发布于 5年前   282

一、前言

项目中前端采用的Element UI 框架, 远程数据请求,使用的是axios,后端接口框架采用的asp.net webapi,数据导出成Excel采用NPOI组件。其业务场景,主要是列表页(如会员信息,订单信息等)表格数据导出,如表格数据进行了条件筛选,则需要将条件传至后端api,筛选数据后,导出成Excel。

思考过前端导出的3种方案:

1.使用location.href 打开接口地址.缺点: 不能传token至后端api, 无法保证接口的安全性校验,并且接口只能是get方式请求.

2.采用axios请求接口,先在筛选后的数据服务端生成文件并保存,然后返回远程文件地址,再采用 location.href打开文件地址进行下载. 缺点: 实现复杂,并且每次导出会在服务端生成文件,但是又没有合适的时机再次触发删除文件,会在服务端形成垃圾数据。优点:每次导出都可以有记录。

3. 采用axios请求接口,服务端api返回文件流,前端接收到文件流后,采用blob对象存储,并创建成url, 使用a标签下载. 优点:前端可传token参数校验接口安全性,并支持get或post两种方式。

因其应用场景是导出Excel文件之前,必须筛选数据,并需要对接口安全进行校验,所以第3种方案为最佳选择。在百度之后,发现目前使用最多的也是第3种方案。

二、Vue + axios 前端处理

1.axios 需在response拦截器里进行相应的处理(这里不再介绍axios的使用, 关于axios的用法,具体请查看Axios中文说明 ,我们在项目中对axios进行了统一的拦截定义). 需特别注意: response.headers['content-disposition'],默认是获取不到的,需要对服务端webapi进行配置,请查看第三点中webapi CORS配置

// respone拦截器service.interceptors.response.use( response => { // blob类型为文件下载对象,不论是什么请求方式,直接返回文件流数据 if (response.config.responseType === 'blob') {  const fileName = decodeURI(  response.headers['content-disposition'].split('filename=')[1]  )// 返回文件流内容,以及获取文件名, response.headers['content-disposition']的获取, 默认是获取不到的,需要对服务端webapi进行配置  return Promise.resolve({ data: response.data, fileName: fileName }) } // 依据后端逻辑实际情况,需要弹窗展示友好错误 }, error => { let resp = error.response if (resp.data) {  console.log('err:' + decodeURIComponent(resp.data)) // for debug } // TODO: 需要依据后端实际情况判断 return Promise.reject(error) })

2. 点击导出按钮,请求api. 需要注意的是接口请求配置的响应类型responseType:'blob' (也可以是配置arrayBuffer) ; 然IE9及以下浏览器不支持createObjectURL. 需要特别处理下IE浏览器将blob转换成文件。

exportExcel () {  let params = {}  let p = this.getQueryParams() // 获取相应的参数  if (p) params = Object({}, params, p)  axios  .get('接口地址', {   params: params,   responseType: 'blob'  })  .then(res => {   var blob = new Blob([res.data], {   type: 'application/vnd.ms-excel;'   })   // 针对于IE浏览器的处理, 因部分IE浏览器不支持createObjectURL   if (window.navigator && window.navigator.msSaveOrOpenBlob) {   window.navigator.msSaveOrOpenBlob(blob, res.fileName)   } else {   var downloadElement = document.createElement('a')   var href = window.URL.createObjectURL(blob) // 创建下载的链接   downloadElement.href = href   downloadElement.download = res.fileName // 下载后文件名   document.body.appendChild(downloadElement)   downloadElement.click() // 点击下载   document.body.removeChild(downloadElement) // 下载完成移除元素   window.URL.revokeObjectURL(href) // 释放掉blob对象   }  }) }

三、WebApi + NPOI 后端处理

1. 需要通过接口参数,查询数据

为了保持与分页组件查询接口一直的参数,采用了get请求方式,方便前端传参。webapi接口必须返回IHttpActionResult 类型

[HttpGet]  public IHttpActionResult ExportData([FromUri]Pagination pagination, [FromUri] OrderReqDto dto)  {   //取出数据源   DataTable dt = this.Service.GetMemberPageList(pagination, dto.ConvertToFilter());   if (dt.Rows.Count > 65535)   {    throw new Exception("最大导出行数为65535行,请按条件筛选数据!");   }   foreach (DataRow row in dt.Rows)   {    var isRealName = row["IsRealName"].ToBool();    row["IsRealName"] = isRealName ? "是" : "否";   }   var model = new ExportModel();   model.Data = JsonConvert.SerializeObject(dt);   model.FileName = "会员信息";   model.Title = model.FileName;   model.LstCol = new List();   model.LstCol.Add(new ExportDataColumn() { prop = "FullName", label = "会员名称" });   model.LstCol.Add(new ExportDataColumn() { prop = "RealName", label = "真实姓名" });   model.LstCol.Add(new ExportDataColumn() { prop = "GradeName", label = "会员等级" });   model.LstCol.Add(new ExportDataColumn() { prop = "Telphone", label = "电话" });   model.LstCol.Add(new ExportDataColumn() { prop = "AreaName", label = "区域" });   model.LstCol.Add(new ExportDataColumn() { prop = "GridName", label = "网格" });   model.LstCol.Add(new ExportDataColumn() { prop = "Address", label = "门牌号" });   model.LstCol.Add(new ExportDataColumn() { prop = "RegTime", label = "注册时间" });   model.LstCol.Add(new ExportDataColumn() { prop = "Description", label = "备注" });   return ExportDataByFore(model);  }

2.关键导出函数 ExportDataByFore的实现

[HttpGet]  public IHttpActionResult ExportDataByFore(ExportModel dto)  {   var dt = JsonConvert.DeserializeObject(dto.Data);   var fileName = dto.FileName + DateTime.Now.ToString("yyMMddHHmmssfff") + ".xls";   //设置导出格式   ExcelConfig excelconfig = new ExcelConfig();   excelconfig.Title = dto.Title;   excelconfig.TitleFont = "微软雅黑";   excelconfig.TitlePoint = 25;   excelconfig.FileName = fileName;   excelconfig.IsAllSizeColumn = true;   //每一列的设置,没有设置的列信息,系统将按datatable中的列名导出   excelconfig.ColumnEntity = new List();   //表头   foreach (var col in dto.LstCol)   {    excelconfig.ColumnEntity.Add(new ColumnEntity() { Column = col.prop, ExcelColumn = col.label });   }   //调用导出方法   var stream = ExcelHelper.ExportMemoryStream(dt, excelconfig); // 通过NPOI形成将数据绘制成Excel文件并形成内存流   var browser = String.Empty;   if (HttpContext.Current.Request.UserAgent != null)   {    browser = HttpContext.Current.Request.UserAgent.ToUpper();   }   HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK);   httpResponseMessage.Content = new StreamContent(stream);   httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); // 返回类型必须为文件流 application/octet-stream   httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") // 设置头部其他内容特性, 文件名   {    FileName =     browser.Contains("FIREFOX")      ? fileName      : HttpUtility.UrlEncode(fileName)   };   return ResponseMessage(httpResponseMessage);  }

3. web api 的CORS配置

采用web api 构建后端接口服务的同学,都知道,接口要解决跨域问题,都需要进行api的 CORS配置, 这里主要是针对于前端axios的响应response header中获取不到 content-disposition属性,进行以下配置

四、总结

以上就是我在实现axios导出Excel文件功能时,遇到的一些问题,以及关键点进行总结。因为项目涉及到前后端其他业务以及公司架构的一些核心源码。要抽离一个完整的demo,比较耗时,所以没有完整demo展示. 但我已把NPOI相关的操作函数源码,整理放至github上。https://github.com/yinboxie/BlogExampleDemo

您可能感兴趣的文章:

  • vue.js中导出Excel表格的案例分析
  • 详解如何在Vue项目中导出Excel
  • Vue结合后台导入导出Excel问题详解
  • vue中导出Excel表格的实现代码
  • vue+springmvc导出excel数据的实现代码
  • Vue实现导出excel表格功能
  • vue2.0 + element UI 中 el-table 数据导出Excel的方法
  • Vue导出json数据到Excel电子表格的示例
  • Vue2.0实现将页面中表格数据导出excel的实例
  • vue+element表格导出为Excel文件


  • 上一条:
    js实现随机8位验证码
    下一条:
    vue-cli3添加模式配置多环境变量的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客