ASP.NET MVC实现Excel文件的上传下载
在应用系统开发当中,文件的上传和下载是非常普遍的需求。在基于.NET的C/S架构的项目开发当中,有多种方案可以实现文件的上传和下载(httpwebrequest、webclient等),而且多采用异步(xxxxAsync或async/await等)的方式实现。而在基于.NET的B/S架构的项目开发当中,虽然webform提供了上传控件(HttpPostFile),但用户体验并不好(页面刷新,如果上传大文件则卡死,即不支持分块上传),虽然有基于Flash的上传文件的解决方案,但Flash已经过时(安全性差)。因此我们一般采用基于h5+js的上传文件插件的解决方案。本文介绍的是使用WebUploader控件结合ASP.NET MVC实现文件的上传、下载以及上传成功后将Excel数据保存到SQL Server数据库中的功能。
关于WebUploader的介绍,读者可以去查看官方网页 http://fex.baidu.com/webuploader/,跟ECharts一样,这也是百度开发的基于h5+js的开源上传文件插件。官网上面也有详细的使用介绍,基本上是介绍了js前端的配置和关键代码,但后端代码并没有提供,需要读者自行实现。
在ASP.NET MVC4中使用WebUploader只需要导入开发包中的js和css文件就可以了。比如:
<link href="@Url.Content("~/Scripts/webuploader/webuploader.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Scripts/webuploader/bootstrap.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Scripts/webuploader/style.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/webuploader/jquery-1.10.2.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/webuploader/bootstrap.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/webuploader/webuploader.js")" type="text/javascript"></script>
然后是Html部分:
<div id="uploader"> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="picker">选择文件</div> <input id="ctlBtn" type="button" value="开始上传" class="btn btn-default" /> @Html.ActionLink("下载Excel", "DownLoad", null, new { @class = "btn btn-default" }) </div> </div>
这里面的id和class都是webuploader默认为我们提供的,后面的btn-default则是bootstrap为我们提供的。
关键的就是js部分代码:
<script type="text/javascript"> var applicationPath = window.applicationPath === "" ? "" : window.applicationPath || "../../"; var GUID = WebUploader.Base.guid(); $(function () { var $ = jQuery; var $list = $('#thelist'); var uploader = WebUploader.create({ auto: false, // 是否自动上传 swf: applicationPath + '../Scripts/webuploader/Uploader.swf', //server: applicationPath + 'DAManage/Upload', server: '@Url.Action("Upload", "Test")', pick: '#picker', accept: { title: 'Excels', extensions: 'xls,xlsx', mimeTypes: 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, chunked: true, //分片上传 chunkSize: 2048000, //每一片的大小 formData: { guid: GUID }, resize: false //不压缩image }); //添加进上传文件队列 uploader.on('fileQueued', function (file) { $list.append('<div id="' + file.id + '" class="item">' + '<h4 class="info">' + file.name + '</h4>' + '<p class="state">等待上传...</p>' + '</div>'); }); //开始上传 $("#ctlBtn").click(function () { uploader.upload(); }); //上传进度 uploader.on('uploadProgress', function (file, percentage) { var $li = $('#' + file.id), $percent = $li.find('.progress .progress-bar'); // 避免重复创建 if (!$percent.length) { $percent = $('<div class="progress progress-striped active">' + '<div class="progress-bar" role="progressbar" style="width: 0%">' + '</div>' + '</div>').appendTo($li).find('.progress-bar'); } $li.find('p.state').text('上传中'); $percent.css('width', percentage * 100 + '%'); }); //上传成功 uploader.on('uploadSuccess', function (file, response) { $('#' + file.id).find('p.state').text('已上传'); $.post('@Url.Action("Merge", "Test")', { guid: GUID, fileName: file.name }, function (data) { $("#uploader .state").html("上传成功..."); uploader.removeFile(file); }); }); // 上传失败 uploader.on('uploadError', function (file) { $('#' + file.id).find('p.state').text('上传出错'); }); //上传完成后 uploader.on('uploadComplete', function (file) { $('#' + file.id).find('.progress').fadeOut(); }); //上传完毕 uploader.on("uploadFinished", function () { uploader.reset(); }); }); </script>
上面我给出了基本的注释,想要获取参数的详细定义和说明,请参考:http://fex.baidu.com/webuploader/doc/index.html。
后端控制器部分代码,主要是上面js中所指向的两个Action,分别为Upload和Merge。
Upload部分代码:
/// <summary> /// 上传Excel /// </summary> /// <returns>1表示失败,0表示成功</returns> [HttpPost] public ActionResult Upload() { var fileName = Request["name"]; var fileRelName = fileName.Substring(0, fileName.LastIndexOf('.')); int index = Convert.ToInt32(Request["chunk"]); var dir = Server.MapPath("~/Upload"); dir = Path.Combine(dir, fileRelName); if (!System.IO.Directory.Exists(dir)) System.IO.Directory.CreateDirectory(dir); try { string filePath = Path.Combine(dir, index.ToString()); var data = Request.Files["file"]; data.SaveAs(filePath); } catch (Exception) { return Json(new { error = 1 }); } return Json(new { erron = 0 }); }
Merge部分代码:
/// <summary> /// 合并Excel成功后,将其数据导入数据库 /// </summary> /// <returns>1表示失败,0表示成功</returns> public ActionResult Merge() { var uploadDir = Server.MapPath("~/Upload"); var fileName = Request["fileName"]; var fileRelName = fileName.Substring(0, fileName.LastIndexOf('.')); var dir = Path.Combine(uploadDir, fileRelName);//临时文件夹 var files = System.IO.Directory.GetFiles(dir); var finalPath = Path.Combine(uploadDir, fileName); var fs = new FileStream(finalPath, FileMode.Create); foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N块写入 { var bytes = System.IO.File.ReadAllBytes(part); fs.Write(bytes, 0, bytes.Length); System.IO.File.Delete(part);//删除分块 } fs.Flush(); fs.Close(); System.IO.Directory.Delete(dir);//删除文件夹 try { //读取上传的Excel并保存到数据库 DbHelper.Excel2DB(finalPath, "Sheet1"); } catch (Exception) { return Json(new { error = 1 }); } return Json(new { error = 0 }); }
WebUploader是基于分块上传(这个设计主要针对大文件的上传)的,所以后端的处理也是分块合并的。Merge中的Excel2DB方法是将上传到服务器的Excel文件中的数据保存到数据库的方法,其中涉及Excel文件内容的读取(NPOI,支持xls和xlsx类型)和EF(5.0)实现数据的保存(保存到SQLServer)。具体的代码可以参考本篇博客最后的示例代码下载。
而关于文件的下载,其实ASP.NET MVC已经提供了FileResult类型,只需要返回File对象就可以了,具体的Action代码如下:
/// <summary> /// 下载excel /// </summary> /// <returns></returns> public FileResult DownLoad() { var path = Server.MapPath("~/Upload/"); var file = System.IO.Directory.GetFiles(path).OrderByDescending(t => new FileInfo(t).CreationTime).FirstOrDefault(); return File(file, "application/vnd.ms-excel", new FileInfo(file).Name); }
File对应的第二个参数是Content-Type,由于这里要下载Excel,所以用了application/vnd.ms-excel。关于如何确定各种文件类型的Content-Type可以查看这个网址里的内容:http://tool.oschina.net/commons。
对应的前端代码上面已经贴过了,代码如下:
@Html.ActionLink("下载Excel", "DownLoad", null, new { @class = "btn btn-default" })
相关文章
- 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面
- 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面
- .NET导入导出Excel
- What is the difference between Version and 'Runtime Version' in .Net?
- ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段
- JavaScript日历控件开发 C# 读取 appconfig文件配置数据库连接字符串,和配置文件 List<T>.ForEach 调用异步方法的意外 ef 增加或者更新的习惯思维 asp.net core导入excel 一个二级联动
- asp.net core导出导入excel
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
- [C#]使用 C# 代码实现拓扑排序 dotNet Core WEB程序使用 Nginx反向代理 C#里面获得应用程序的当前路径 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法 .Net程序员 初学Ubuntu ,配置Nignix 夜深了,写了个JQuery的省市区三级级联效果
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- Aspose.Words for .NET使用表格教程之处理合并的单元格
- asp.net, c# 查询某天所有数据sql语句 用于SQLServer(mssql)
- Asp.Net中使用OpenRowSet操作Excel表,导入Sql Server(实例)
- .NET/Mysql-petatoco连接mysql数据库
- Excel VLOOKUP实用教程之 02 vlookup如何双向查找,两个字段查询数据?(教程含数据excel)
- Python Excel教程之如何将多个 excel 文件合并为一个文件(教程含源码)
- Excel VLOOKUP实用教程之 03 使用下拉列表作为查找值vlookup?(教程含数据excel)
- Excel VLOOKUP实用教程之 07 vlookup如何解决肉眼看完全匹配,但是就是返回N/A错误(教程含数据excel)
- Excel VLOOKUP实用教程之 10 在使用 VLOOKUP 函数时处理错误?(教程含数据excel)
- Asp.Net读取服务器EXE文件的方法!(超简单实例)
- delphi如何按照控件的左右顺序来遍历窗体中的每个控件 [问题点数:20 http://bbs.csdn.net/topics/380216822
- .net core 压缩数据、用户响应压缩
- Creating the Help Page in ASP.NET Web API
- 怎么解决Chrome浏览器“Failed to load resource: net::ERR_INSECURE_RESPONSE”错误?