C#与Vue2上传下载Excel文件

embedded/2025/1/17 18:34:35/

1、上传文件流程:先上传文件,上传成功,返回文件名与url,然后再次发起请求保存文件名和url到数据库

        前端Vue2代码:

        使用element的el-upload组件,action值为后端接收文件接口,headers携带session信息,成功后调用onsuccess对应的方法保存文件信息

 <el-upload :action="uploadUrl" :headers="uploadHeaders" accept=".xlsx" :show-file-list="false":limit="1" ref="upload" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"><el-button type="primary">导入</el-button></el-upload>

     

beforeAvatarUpload (res) {const isExcel = /\.(xlsx)$/.test(res.name);if (!isExcel) {toast.error('只能读取.xlsx文件,请另存为.xlsx文件!');return false}const fileSuffix = res.name.substring(res.name.lastIndexOf(".") + 1);const list = ["exe"]if (list.indexOf(fileSuffix) >= 0) {toast.error(list.toString() + '文件类型限制传入!')return false}if (res.size / 1024 / 1024 > 50) {toast.error('文件大小不能超过50MB!')return false}return true},//上传成功开始保存本条数据handleAvatarSuccess (res, file) {if (res.code == apiCode.Success) {let instance = {stationId: this.stationId,originalFileName: res.data.attachmentName,newFileName: res.data.fileName,Url: res.data.url,}this.$axios.post(ZlCustomeTimeFile.Save, instance).then(response => {let res = response.data;if (res.code == apiCode.Success) {this.getData()toast.success()} else {toast.error(res.msg)}})} else {toast.error(res.msg)}},

          后端代码C#,aspnet core,接收文件并保存到服务器,然后返回文件信息:

        [HttpPost]public async Task<ApiResult<ImageUploadResponse>> UploadFileAsync(List<IFormFile> file){if (file?.Count > 0){}else{return base.DoFail<ImageUploadResponse>(ApiCode.Fail, msg: $"上传文件失败,请选择文件");}var exMsg = "";var formFile = file[0];try{var filePath = $"/upload/";System.IO.Directory.CreateDirectory(_hostingEnvironment.WebRootPath + filePath);Random rd = new Random();                string FileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + rd.Next(100, 1000) + formFile.FileName.Substring(formFile.FileName.LastIndexOf(".") == -1 ? 0 : formFile.FileName.LastIndexOf("."));using (var stream = System.IO.File.Create(_hostingEnvironment.WebRootPath + filePath + FileName)){await formFile.CopyToAsync(stream);}var request = HttpContext.Request;return base.DoSuccess<ImageUploadResponse>(new ImageUploadResponse{Url = $"{request.Scheme}://{request.Host.Host}{(request.Host.Port == 80 ? "" : ":" + request.Host.Port)}" + filePath + FileName,FileName = FileName,AttachmentName = formFile.FileName,});}catch (Exception ex){exMsg = ex.Message;}return base.DoFail<ImageUploadResponse>(ApiCode.Fail, msg: $"上传文件失败,{exMsg}");}

2、静态a标签下载文件

<a target="_blank" :href="row.url">{{ row.originalFileName }}
<el-link :href="row.url">{{ row.originalFileName }}</el-link>

3、动态a标签下载文件,使用二进制流blob直接下载,可以修改文件名

<span style="cursor: pointer;" @click="down(row)">{{ row.originalFileName }}</span>
        //路径转为相对路径,然后使用二进制流blob直接下载,可以修改文件名down (data) {var newurl = data.url.substring(data.url.indexOf("//") + 2)console.log(newurl)newurl = newurl.substring(newurl.indexOf("/"))console.log(newurl)const x = new XMLHttpRequest()x.open('GET', newurl, true)x.responseType = 'blob'x.onload = () => {const url = window.URL.createObjectURL(x.response)// 创建隐藏的可下载链接var eleLink = document.createElement('a');eleLink.download = data.originalFileName;eleLink.style.display = 'none';// 下载内容转变成blob地址eleLink.href = url;// 触发点击document.body.appendChild(eleLink);eleLink.click();// 然后移除document.body.removeChild(eleLink);}x.send()},

4、动态下载Excel文件,使用二进制流blob,前端vue2下载按钮事件,后端C#接口代码:

     import { saveAs } from 'file-saver';downloadControllerAction (row) {var that = this;this.$axios.get(CustomeTimeFile.Download, {params: { id: row.id },responseType: 'blob'}).then(response => {console.log(response)if (response.status !== 200) {toast.error('下载失败');return;}const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });saveAs(blob, row.originalFileName); // 直接调用saveAs函数}).catch((error) => {console.log(error);let errorMessage = '';if (error instanceof Blob) {const reader = new FileReader();reader.onload = function (e) {try {const errorJson = JSON.parse(e.target.result);errorMessage = errorJson.message || '出现错误';} catch (err) {errorMessage = '下载错误,请重新下载.';}toast.error(errorMessage);};reader.readAsText(error);} else {errorMessage = error.message;console.error('出现错误:', errorMessage);toast.error(errorMessage);}});},
public async Task<IActionResult> Download([FromQuery] long id){var fileInfo = DapperContext.GetDatabase().Get<ZustomeTimeFile>(id);if (fileInfo == null || fileInfo.Url.IsNullOrEmpty()) return StatusCode(500, new { Message = "找不到文件,请重新上传统计" });var energylist = CustomeTimeEnergyRepository.GetListByFile(fileInfo.StationId, fileInfo.Id);var energydict = energylist.GroupBy(t => t.RowNumber).ToDictionary(t => t.Key, t => t.First());try{               byte[] fileBytes = null;var filePath = $"/upload/";var fileName = fileInfo.NewFileName;try{fileBytes = System.IO.File.ReadAllBytes(_hostingEnvironment.WebRootPath + filePath + fileName);}catch (Exception ex1){LogHelper.WriteInfo("读取文件异常," + ex1);return StatusCode(500, new { Message = "找不到已上传文件,请重新上传" });}// 从URL下载Excel文件到字节数组,内部网络权限设置,不允许从外网访问,改为直接从服务器下载//try//{//    fileBytes = await HttpClientHelper.DownloadFileAsync(fileInfo.Url);//}//catch (Exception ex)//{//    return StatusCode(500, new { Message = "找不到已上传文件,请重新上传" });//}// 使用NPOI解析Excel文件using (MemoryStream memoryStream = new MemoryStream(fileBytes, true)){IWorkbook workbook = null;// 确定文件格式并创建相应的工作簿对象if (fileInfo.Url.EndsWith(".xlsx")) workbook = new XSSFWorkbook(memoryStream);else if (fileInfo.Url.EndsWith(".xls")) workbook = new HSSFWorkbook(memoryStream);if (workbook != null){ISheet sheet = workbook.GetSheetAt(0);foreach (IRow row in sheet){if (energydict.ContainsKey(row.RowNum)){ICell cell = row.GetCell(5) ?? row.CreateCell(5);if (energydict[row.RowNum].ElectricityValue.HasValue){cell.SetCellValue((double)energydict[row.RowNum].ElectricityValue);}cell = row.GetCell(6) ?? row.CreateCell(6);if (energydict[row.RowNum].NaturalGasValue.HasValue){cell.SetCellValue((double)energydict[row.RowNum].NaturalGasValue);}cell = row.GetCell(7) ?? row.CreateCell(7);if (!energydict[row.RowNum].StatisticMessage.IsNullOrEmpty()){cell.SetCellValue(energydict[row.RowNum].StatisticMessage);}}}}using (var stream = new MemoryStream()){workbook.Write(stream);workbook.Close();stream.Flush();// 设置响应头以提示浏览器下载文件return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileInfo.OriginalFileName);}}}catch (Exception ex){return StatusCode(500, new { Message = "出现异常:" + ex.Message });}}}

5、读取Excel文件,NPOI方式

        public async Task<ApiResult> Save(CustomeTimeFile instance){instance.UploadTime = DateTime.Now;instance.DateCode = instance.UploadTime.ToDateCode();instance.IsStatistic = 0;instance.UploaderName = CurrentUser.RealName;var id = DapperContext.GetDatabase().Insert(instance);if (id > 0){var list = new List<CustomeTimeEnergy>();try{// 从URL下载Excel文件到字节数组,旧版本从下载链接直接读取,但是网络权限网关限制不允许外网读取,修改为直接读取文件//byte[] fileBytes = await HttpClientHelper.DownloadFileAsync(instance.Url);var filePath = $"/upload/";var fileName = instance.NewFileName;byte[] fileBytes = new byte[0];try{fileBytes = System.IO.File.ReadAllBytes(_hostingEnvironment.WebRootPath + filePath + fileName);}catch (Exception ex1){LogHelper.WriteInfo("读取文件异常," + ex1);throw;}// 使用NPOI解析Excel文件using (MemoryStream memoryStream = new MemoryStream(fileBytes)){IWorkbook workbook = null;// 确定文件格式并创建相应的工作簿对象try{if (instance.Url.EndsWith(".xlsx")) workbook = new XSSFWorkbook(memoryStream);else if (instance.Url.EndsWith(".xls")) workbook = new HSSFWorkbook(memoryStream);}catch (Exception exx){LogHelper.WriteInfo($"读取到workbook异常={exx}");}if (workbook != null){ISheet sheet = workbook.GetSheetAt(0);foreach (IRow row in sheet){var rowNum = row.RowNum; // 使用 RowNum 属性获取行号var deviceName = row.Cells[0].StringCellValue;var startTime = row.Cells[1].DateCellValue;var endTime = row.Cells[3].DateCellValue;if (deviceName.IsNullOrEmpty() || startTime.HasValue == false || endTime.HasValue == false) continue;list.Add(new CustomeTimeEnergy(){StationId = instance.StationId,UploadFileId = (int)id,RowNumber = rowNum,ClassificationSubitemId = 0,ClassificationSubitemName = deviceName,StartTime = startTime,EndTime = endTime,CollectTime = startTime.Value.Date,IsStatistic = 0,DateCode = startTime.Value.ToDateCode(),RecordTime = instance.UploadTime,});}}workbook.Close();}CustomeTimeEnergyRepository.BatchInsert(list);}catch (Exception ex){DoFail($"保存失败:{ex.Message}");}return DoSuccess();}return DoFail("保存失败");}


http://www.ppmy.cn/embedded/154726.html

相关文章

flutter 使用google_mlkit_image_labeling做图片识别

在AI横行的如今&#xff0c;相信大家或多或少都做过跟AI接轨的需求了吧&#xff1f;今天我说的是关于图片识别的需求&#xff0c;flutter的专属图片识别插件google_mlkit_image_labeling。 google_mlkit_image_labeling它是Google旗下的Google Cloud Vision API中分支出来的一部…

LVS四层反向代理

这里写自定义目录标题 一、LVS四层反向代理架构的组成部分1. 负载调度器&#xff08;Director/Load Balancer&#xff09;&#xff1a;2. 服务器池&#xff08;Real Server/Server Pool&#xff09;&#xff1a;3. 共享存储&#xff08;Shared Storage&#xff09;&#xff08;…

02、Redis从入门到放弃 之 常用命令和基本数据类型操作

Redis从入门到放弃 之 常用命令和基本数据类型操作 一、Redis通用命令 redis-cli -h 127.0.0.1 -p 6379 redis客户端登录 -h host -p 端口 -a 密码exit 退出当前客户端info 返回redis的一些相关信息&#xff08;包括端口、配置文件等&#xff09;flushdb 清空当前库…

YOLOv8从菜鸟到精通(二):YOLOv8数据标注以及模型训练

数据标注 前期准备 先打开Anaconda Navigator&#xff0c;点击Environment&#xff0c;再点击new(new是我下载anaconda的文件夹名称)&#xff0c;然后点击创建 点击绿色按钮&#xff0c;并点击Open Terminal 输入labelimg便可打开它,labelimg是图像标注工具&#xff0c;在上篇…

Vue API 盲点解析

在了解了一些实用的开发技巧和编码理念后&#xff0c;我们在项目的开发过程中难免也会遇到因为不熟悉 Vue API 而导致的技术问题&#xff0c;而往往就是这样的一些问题消耗了我们大量的开发时间&#xff0c;造成代码可读性下降、功能紊乱甚至 bug 量的增加&#xff0c;其根本原…

MySQL:表的内外连接

目录 1.内连接 2.左外连接和右外连接 178. 分数排名 - 力扣&#xff08;LeetCode&#xff09; 1.内连接 内连接就是两张表做笛卡尔积&#xff0c;再加上一个筛选条件。 这两个sql语句是一样的。 2.左外连接和右外连接 左外连接就是左表必须是完全显示&#xff0c;即使筛选…

ubuntu的截图工具有哪些

在 Ubuntu 上&#xff0c;有多种截图工具可供选择&#xff0c;以下是一些常用的工具及其使用方法&#xff1a; 1. 内置截图工具 Ubuntu 自带了一个简单的截图工具&#xff0c;可以通过快捷键或应用程序启动。 快捷键&#xff1a; 全屏截图&#xff1a;Print Screen&#xff08…

BY组态-低代码web可视化组件

简介 BY组态是贵州华创云科技完全自主研发的集实时数据展示、动态交互等一体的全功能可视化平台。帮助物联网、工业互联网、电力能源、水利工程、智慧农业、智慧医疗、智慧城市等场景快速实现数字孪生、大屏可视化、Web组态、SCADA等解决方案。具有实时监控、多样、变化、动态…