vue实现Excel文件的上传与下载功能的两种方式


Posted in Javascript onJune 28, 2019

一.前言项目中使用到比较多的关于Excel的前端上传与下载,整理出来,以便后续使用或分析他人。

1.前端vue:模板下载与导入Excel

导入Excel封装了子组件,点击导入按钮可调用子组件,打开文件上传的对话框,上传成功后返回结果

<el-col style="padding: 10px 0 20px;">
    <el-button
     class="pull-right"
     icon="el-icon-upload"
     type="primary"
     size="mini"
     @click="importFile()"
    >批量导入</el-button>
    <el-button
     class="pull-right right-10"
     icon="el-icon-download"
     type="primary"
     size="mini"
     @click="downloadFile('档案模板')"
    >模板下载</el-button>
    <el-button
     size="mini"
     type="primary"
     icon="el-icon-plus"
     class="pull-right"
     @click="addRow"
    >新增</el-button>
    <div class="pull-right">
     <el-input
      placeholder="请输入编码,名称"
      prefix-icon="el-icon-search"
      v-model="FinQueryParams.archiveFilter"
      size="mini"
     ></el-input>
    </div>
   </el-col>

 <!-- 批量导入Dialog开始 -->
  <uploadTemp
   :apiURL="fileUploadUrl"
   ref="refFileUpload"
   :Refresh="Refresh"
   :OtherParams="{brandId: QueryParams.BrandID}"
  ></uploadTemp>
  <!-- 批量导入Dialog结束 -->
importFile() {
  this.$refs.refFileUpload.open();
 } 

向后台提交文件的方法

submitFile() {
   const _this = this;
   if (!_this.files.name) {
    _this.$message.warning("请选择要上传的文件!");
    return false;
   }
   let fileFormData = new FormData();
   //filename是键,file是值,就是要传的文件
   fileFormData.append("file", _this.files, _this.files.name);
   if(_this.OtherParams){
    const keys=Object.keys(_this.OtherParams);
    keys.forEach(e=>{
     fileFormData.append(e, _this.OtherParams[e]);
    })
   }
   let requestConfig = {
    headers: {
     "Content-Type": "multipart/form-data"
    }
   };
   AjaxHelper.post(_this.apiURL, fileFormData, requestConfig)
    .then(res => {
     console.log(res);
     if (res.success) {
      const result = res.result;
      if (result.errorCount == 0 && result.successCount > 0) {
       _this.$message({
        message: `导入成功,成功${result.successCount}条`,
        type: "success"
       });
       _this.closeFileUpload();
       _this.Refresh();
      } else if (result.errorCount > 0 && result.successCount >= 0) {
       _this.Refresh();
       _this.tableData = result.uploadErrors;
       _this.successCount = result.successCount;
       _this.innerVisible = true;
      } else if (result.errorCount == 0 && result.successCount == 0) {
       _this.$message({
        message: `上传文件中数据为空`,
        type: "error"
       });
      }
     }
    })
    .catch(function(error) {
     console.log(error);
    });
  },

这是上传文件的调用方法。

2.模板下载

关于模板下载,之前没有考虑到IE10浏览器的兼容问题,导致在IE10下文件没法下载,后来百度后找到了解决办法。

downloadFile(name) {
   let requestConfig = {
    headers: {
     "Content-Type": "application/json;application/octet-stream"
    }
   };
   AjaxHelper.post(this.downLoadUrl, requestConfig, {
    responseType: "blob"
   }).then(res => {
    // 处理返回的文件流
    const content = res.data;
    const blob = new Blob([content]);
    var date =
     new Date().getFullYear() +
     "" +
     (new Date().getMonth() + 1) +
     "" +
     new Date().getDate();
    const fileName = date + name + ".xlsx";
    if ("download" in document.createElement("a")) {
     // 非IE下载
     const elink = document.createElement("a");
     elink.download = fileName;
     elink.style.display = "none";
     elink.href = URL.createObjectURL(blob);
     document.body.appendChild(elink);
     elink.click();
     URL.revokeObjectURL(elink.href); // 释放URL 对象
     document.body.removeChild(elink);
    } else {
     // IE10+下载
     navigator.msSaveBlob(blob, fileName);
    }
   });
  },

前端的处理就结束了。

3.后端对于文件上传和下载的处理

文件上传

public UploadResult UploadFiles(IFormFile file, Guid brandId)
    {
      try
      {
        UploadResult uploadResult = new UploadResult();
        if (file == null)
        {
          throw new UserFriendlyException(501, "上传的文件为空,请重新上传");
        }
        string filename = Path.GetFileName(file.FileName);
        string fileEx = Path.GetExtension(filename);//获取上传文件的扩展名
        string NoFileName = Path.GetFileNameWithoutExtension(filename);//获取无扩展名的文件名
        string FileType = ".xls,.xlsx";//定义上传文件的类型字符串
        if (!FileType.Contains(fileEx))
        {
          throw new UserFriendlyException(501, "无效的文件类型,只支持.xls和.xlsx文件");
        }
        //源数据
        MemoryStream msSource = new MemoryStream();
        file.CopyTo(msSource);
        msSource.Seek(0, SeekOrigin.Begin);
        DataTable sourceExcel = ReadStreamToDataTable(msSource, "", true);

        //模板数据
        string dataDir = _hosting.WebRootPath;//获得当前服务器程序的运行目录 
        dataDir = Path.Combine(dataDir, "ExcelTemplate");
        var path = dataDir + "//档案模版.xlsx";
        MemoryStream msModel = new MemoryStream();
        FileStream stream = new FileStream(path, FileMode.Open);
        stream.CopyTo(msModel);
        msModel.Seek(0, SeekOrigin.Begin);
        DataTable templateExcel = ReadStreamToDataTable(stream, "", true);
        //验证是否同模板相同 
        string columnName = templateExcel.Columns[0].ColumnName;
        if (columnName != sourceExcel.Columns[0].ColumnName)
        {
          throw new UserFriendlyException(501, "上传的模板文件不正确");
        }
        int sucessCount = 0;
        int errorCount = 0;
        // 处理后台逻辑 执行 插入操作

        uploadResult.SuccessCount = sucessCount;
        uploadResult.ErrorCount = errorCount;
        uploadResult.uploadErrors = errorList;
        return uploadResult;
      }
      catch (Exception ex)
      {
        throw new UserFriendlyException(501, "上传的模板文件不正确");
      }
    }

将文件流转化为Datable

public static DataTable ReadStreamToDataTable(Stream fileStream, string sheetName = null, bool isFirstRowColumn = true)
    {
      //定义要返回的datatable对象
      DataTable data = new DataTable();
      //excel工作表
      ISheet sheet = null;
      //数据开始行(排除标题行)
      int startRow = 0;
      try
      {
        //根据文件流创建excel数据结构,NPOI的工厂类WorkbookFactory会自动识别excel版本,创建出不同的excel数据结构
        IWorkbook workbook = WorkbookFactory.Create(fileStream);
        //如果有指定工作表名称
        if (!string.IsNullOrEmpty(sheetName))
        {
          sheet = workbook.GetSheet(sheetName);
          //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet
          if (sheet == null)
          {
            sheet = workbook.GetSheetAt(0);
          }
        }
        else
        {
          //如果没有指定的sheetName,则尝试获取第一个sheet
          sheet = workbook.GetSheetAt(0);
        }
        if (sheet != null)
        {
          IRow firstRow = sheet.GetRow(0);
          //一行最后一个cell的编号 即总的列数
          int cellCount = firstRow.LastCellNum;
          //如果第一行是标题列名
          if (isFirstRowColumn)
          {
            for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
            {
              ICell cell = firstRow.GetCell(i);
              if (cell != null)
              {
                string cellValue = cell.StringCellValue;
                if (cellValue != null)
                {
                  DataColumn column = new DataColumn(cellValue);
                  data.Columns.Add(column);
                }
              }
            }
            startRow = sheet.FirstRowNum + 1;
          }
          else
          {
            startRow = sheet.FirstRowNum;
          }
          //最后一列的标号
          int rowCount = sheet.LastRowNum;
          for (int i = startRow; i <= rowCount; ++i)
          {
            IRow row = sheet.GetRow(i);
            if (row == null || row.FirstCellNum < 0) continue; //没有数据的行默认是null

 

            DataRow dataRow = data.NewRow();
            for (int j = row.FirstCellNum; j < cellCount; ++j)
            {
              //同理,没有数据的单元格都默认是null
              ICell cell = row.GetCell(j);
              if (cell != null)
              {
                if (cell.CellType == CellType.Numeric)
                {
                  //判断是否日期类型
                  if (DateUtil.IsCellDateFormatted(cell))
                  {
                    dataRow[j] = row.GetCell(j).DateCellValue;
                  }
                  else
                  {
                    dataRow[j] = row.GetCell(j).ToString().Trim();
                  }
                }
                else
                {
                  dataRow[j] = row.GetCell(j).ToString().Trim();
                }
              }
            }
            data.Rows.Add(dataRow);
          }
        }
        return data;
      }
      catch (Exception ex)
      {
        throw ex;
      }

    }
文件下载比较简单

 public async Task<FileStreamResult> DownloadFiles()
    {
      string dataDir = _hosting.WebRootPath;//获得当前服务器程序的运行目录 
      dataDir = Path.Combine(dataDir, "ExcelTemplate");
      var path = dataDir + "//档案模版.xlsx";
      var memoryStream = new MemoryStream();
      using (var stream = new FileStream(path, FileMode.Open))
      {
        await stream.CopyToAsync(memoryStream);
      }
      memoryStream.Seek(0, SeekOrigin.Begin);
      return new FileStreamResult(memoryStream, "application/octet-stream");//文件流方式,指定文件流对应的ContenType。
    }

文件下载比较简单

public async Task<FileStreamResult> DownloadFiles()
    {
      string dataDir = _hosting.WebRootPath;//获得当前服务器程序的运行目录 
      dataDir = Path.Combine(dataDir, "ExcelTemplate");
      var path = dataDir + "//档案模版.xlsx";
      var memoryStream = new MemoryStream();
      using (var stream = new FileStream(path, FileMode.Open))
      {
        await stream.CopyToAsync(memoryStream);
      }
      memoryStream.Seek(0, SeekOrigin.Begin);
      return new FileStreamResult(memoryStream, "application/octet-stream");//文件流方式,指定文件流对应的ContenType。
    }

文件上传结果通知类

public class UploadResult
  {
    public int RepeatCount { get; set; }
    public int SuccessCount { get; set; }
    public int FileRepeatCount { get; set; }
    public int ErrorCount { get; set; }
    public List<UploadErrorDto> uploadErrors { get; set; }
  }
  public class UploadErrorDto
  {
    public string RowIndex { get; set; }
    public string ErrorCol { get; set; }
    public string ErrorData { get; set; }
  } 

 通过以上处理后,我们就可以在前端实现文件的上传了,若上传失败则会返回失败结果

 以上就是整个前后端关于文件上传与下载的实现,想通过日常记录这种方式,来帮助自己更好的掌握基础,稳固自己的技能

总结

以上所述是小编给大家介绍的vue实现Excel文件的上传与下载功能的两种方式,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
用cookies实现的可记忆的样式切换效果代码下载
Dec 24 Javascript
jQuery选中select控件 无法设置selected的解决方法
Sep 01 Javascript
基于jquery的设置页面文本框 只能输入数字的实现代码
Apr 19 Javascript
javascript实现数字验证码的简单实例
Feb 10 Javascript
判断在css加载完毕后执行后续代码示例
Sep 03 Javascript
JS排序方法(sort,bubble,select,insert)代码汇总
Jan 30 Javascript
jQuery代码实现图片墙自动+手动淡入淡出切换效果
May 09 Javascript
JavaScript简单获取页面图片原始尺寸的方法
Jun 21 Javascript
利用AngularJs实现京东首页轮播图效果
Sep 08 Javascript
微信小程序中顶部导航栏的实现代码
Mar 30 Javascript
jQuery图片查看插件Magnify开发详解
Dec 25 jQuery
js实现文件上传功能 后台使用MultipartFile
Sep 08 Javascript
开发中常用的25个JavaScript单行代码(小结)
Jun 28 #Javascript
微信小程序身份证验证方法实现详解
Jun 28 #Javascript
jQuery属性选择器用法实例分析
Jun 28 #jQuery
jQuery位置选择器用法实例分析
Jun 28 #jQuery
jQuery层叠选择器用法实例分析
Jun 28 #jQuery
jQuery内容选择器与表单选择器实例分析
Jun 28 #jQuery
jQuery子选择器与可见性选择器实例分析
Jun 28 #jQuery
You might like
php图像处理函数大全(推荐收藏)
2013/07/11 PHP
封装ThinkPHP的一个文件上传方法实例
2014/10/31 PHP
浅谈PDO的rowCount函数
2015/06/18 PHP
PHP生成推广海报的方法分享
2018/04/22 PHP
Js之软键盘实现(js源码)
2007/01/30 Javascript
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
一些不错的js函数ajax
2008/08/20 Javascript
THREE.JS入门教程(1)THREE.JS使用前了解
2013/01/24 Javascript
一个Action如何调用两个不同的方法
2014/05/22 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
2017/08/18 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
解决vue watch数据的方法被调用了两次的问题
2020/11/07 Javascript
JS实现公告上线滚动效果
2021/01/10 Javascript
python列表去重的二种方法
2014/02/14 Python
django轻松使用富文本编辑器CKEditor的方法
2017/03/30 Python
简单实现python聊天程序
2018/04/01 Python
用Python实现读写锁的示例代码
2018/11/05 Python
python画图系列之个性化显示x轴区段文字的实例
2018/12/13 Python
Python写一个基于MD5的文件监听程序
2019/03/11 Python
Python socket实现的文件下载器功能示例
2019/11/15 Python
Django项目使用ckeditor详解(不使用admin)
2019/12/17 Python
css3一个简易的 LED 数字时钟实现方法
2020/01/15 HTML / CSS
HTML5 Canvas渐进填充与透明实现图像的Mask效果
2013/07/11 HTML / CSS
丝芙兰巴西官方商城:SEPHORA巴西
2016/10/31 全球购物
adidas菲律宾官网:adidas PH
2020/02/07 全球购物
Currentbody美国/加拿大:美容仪专家
2020/03/09 全球购物
酒店实习个人鉴定
2013/12/07 职场文书
保护环境倡议书100字
2014/05/19 职场文书
学习礼仪心得体会
2014/09/01 职场文书
水利局群众路线专题民主生活会发言材料
2014/09/21 职场文书
房屋租赁协议书
2014/10/18 职场文书
2014年销售经理工作总结
2014/12/01 职场文书
医院合作意向书范本
2015/05/08 职场文书
浅谈mysql返回Boolean类型的几种情况
2021/06/04 MySQL