本君已成夜猫子,本节我们来讲讲 ASP.NET Core MVC 中的上传,这两天在研究批量导入功能,本节顺便简单搞搞导入、导出,等博主弄妥当了再来和大家一并分享。
首先我们来看看官网的上传的例子,再然后进行拓展训练,官网的表单是这样的。
- "post" enctype="multipart/form-data" asp-controller="UploadFiles" asp-action="Index">
- class="form-group">
- class="col-md-10">
- Upload one or more files
- using this form:
- "file" name="files" multiple />
- class="form-group">
- class="col-md-10">
- "submit" value="上传" />
在 ASP.NET Core MVC 中接收上传的文件需要用 IFormFile 来接收,该接口定义如下:
- public interface IFormFile {
- string ContentType {
- get;
- }
- string ContentDisposition {
- get;
- }
- IHeaderDictionary Headers {
- get;
- }
- long Length {
- get;
- }
- string Name {
- get;
- }
- string FileName {
- get;
- }
- Stream OpenReadStream();
- void CopyTo(Stream target);
- Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
- }
后台控制器关于上传的 Action 方法进行如下定义:
- [HttpPost("UploadFiles")]
- public async Task Post(List files)
- {
- long size = files.Sum(f => f.Length);
- // full path to file in temp location
- var filePath = Path.GetTempFileName();
- foreach (var formFile in files)
- {
- if (formFile.Length > 0)
- {
- using (var stream = new FileStream(filePath, FileMode.Create))
- {
- await formFile.CopyToAsync(stream);
- }
- }
- }
- return Ok(new { count = files.Count, size, filePath });
- }
为了很清楚地上传文件所在目录,我们将官网例子进行一下改造。
- public IActionResult UploadFiles(List files)
- {
- long size = 0;
- foreach (var file in files)
- {
- //var fileName = file.FileName;
- var fileName = ContentDispositionHeaderValue
- .Parse(file.ContentDisposition)
- .FileName
- .Trim('"');
- fileName = hostingEnv.WebRootPath + $@"\{fileName}";
- size += file.Length;
- using (FileStream fs = System.IO.File.Create(fileName))
- {
- file.CopyTo(fs);
- fs.Flush();
- }
- }
- ViewBag.Message = $"{files.Count}个文件 /{size}字节上传成功!";
- return View();
- }
如上通过注入 private IHostingEnvironment hostingEnv; 来获取网站根目录路径。在前台表单中请求 action 方法用渲染的方式,如下:
- "post" enctype="multipart/form-data" asp-controller="Upload" asp-action="UploadFiles">
当然别忘记添加 TagHelper:
- @addTagHelper * ,
- Microsoft.AspNetCore.Mvc.TagHelpers
成功上传我们显示上传字节大小,如下:
上传的文件在网站根目录下我们能够看到,如下:
上述我们只是牛刀小试通过表单提交,接下来我们进行拓展通过 Ajax 来提交。我们将表单类型 submit 修改为 button,如下:
- class="row">
- class="form-group">
- class="col-md-10">
- 使用表单上传多个文件
- "file" id="files" name="files" multiple />
- @ViewBag.Message
- class="row">
- class="form-group">
- class="col-md-10">
- "button" id="upload" class="btn btn-success" style="cursor:pointer;width:100px;" value="上传" />
我们通过 FormData 对象来获取文件从而进行 Ajax 提交,如下:
- $(function () {
- $("#upload").click(function (evt) {
- var fileUpload = $("#files").get(0);
- var files = fileUpload.files;
- var data = new FormData();
- for (var i = 0; i < files.length ; i++) {
- data.append(files[i].name, files[i]);
- }
- $.ajax({
- type: "POST",
- url: "/Upload/UploadFiles",
- contentType: false,
- processData: false,
- data: data,
- success: function (message) {
- alert(message);
- },
- error: function () {
- alert("上传文件出现错误!");
- }
- });
- });
- });
此时后台则需要进行略微修改,我们不再需要 IFormFile 接口来获取文件,通过请求中的表单获取,如下:
- public IActionResult UploadFiles()
- {
- long size = 0;
- var files = Request.Form.Files;
- foreach (var file in files)
- {
- //var fileName = file.FileName;
- var fileName = ContentDispositionHeaderValue
- .Parse(file.ContentDisposition)
- .FileName
- .Trim('"');
- fileName = hostingEnv.WebRootPath + $@"\{fileName}";
- size += file.Length;
- using (FileStream fs = System.IO.File.Create(fileName))
- {
- file.CopyTo(fs);
- fs.Flush();
- }
- }
- ViewBag.Message = $"{files.Count}个文件 /{size}字节上传成功!";
- return View();
- }
到这里关于 ASP.NET Core MVC 中的上传就告一段落,还是比较简单但是算是比较常见的需求。
项目中需要用到批量导入和导出于是进行了一点研究,.net core 刚出世时还未有对于. net core 中 Excel 的导出,但是见过园中有热心园友分享并制作了. net core 中导出 Excel,但是博主发现在 2 月 19 号有老外已针对. net core 的 Excel 导出和导入目前版本为 1.3 基于 EPPlus,功能和 EPPlus 差不多,不过是移植到了. net core 中,下面我们一起来看看。首先我们下载 EPPlus.Core 程序包,如下:
我们直接上导出代码:
- [HttpGet]
- [Route("Export")]
- public string Export()
- {
- string sWebRootFolder = _hostingEnvironment.WebRootPath;
- string sFileName = @"Jeffcky.xlsx";
- string URL = string.Format("{0}://{1}/{2}", Request.Scheme, Request.Host, sFileName);
- FileInfo file = new FileInfo(Path.Combine(sWebRootFolder, sFileName));
- if (file.Exists)
- {
- file.Delete();
- file = new FileInfo(Path.Combine(sWebRootFolder, sFileName));
- }
- using (ExcelPackage package = new ExcelPackage(file))
- {
- // add a new worksheet
- ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Jeffcky");
- //sheet header
- worksheet.Cells[1, 1].Value = "ID";
- worksheet.Cells[1, 2].Value = "Name";
- worksheet.Cells[1, 3].Value = "Age";
- //Add values
- worksheet.Cells["A2"].Value = 1000;
- worksheet.Cells["B2"].Value = "Jeffcky1";
- worksheet.Cells["C2"].Value = 18;
- worksheet.Cells["A3"].Value = 1001;
- worksheet.Cells["B3"].Value = "Jeffcky2";
- worksheet.Cells["C3"].Value = 19;
- package.Save(); //Save the workbook.
- }
- return URL;
- }
这里我们进行统一封装下来进行导出只需要设置导出属性和列表数据即可,如下:
- public IActionResult Export() {
- var properties = new PropertyByName[] {
- new PropertyByName("Id", d = >d.Id),
- new PropertyByName("Name", d = >d.Name),
- new PropertyByName("Age", d = >d.Age)
- };
- var list = new List() {
- new Person() {
- Id = 1,
- Name = "Jeffcky1",
- Age = 18
- },
- new Person() {
- Id = 2,
- Name = "Jeffcky2",
- Age = 19
- },
- new Person() {
- Id = 3,
- Name = "Jeffcky3",
- Age = 20
- },
- new Person() {
- Id = 4,
- Name = "Jeffcky4",
- Age = 21
- },
- new Person() {
- Id = 5,
- Name = "Jeffcky5",
- Age = 22
- }
- };
- var bytes = _ExportManager.ExportToXlsx(properties, list);
- return new FileContentResult(bytes, MimeTypes.TextXlsx);
- }
说完导出我们再来看导入,我们来读取刚刚导入的数据返回到页面上:
- public string Import()
- {
- string sWebRootFolder = _hostingEnvironment.WebRootPath;
- string sFileName = @"Jeffcky.xlsx";
- FileInfo file = new FileInfo(Path.Combine(sWebRootFolder, sFileName));
- try
- {
- using (ExcelPackage package = new ExcelPackage(file))
- {
- StringBuilder sb = new StringBuilder();
- ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
- int rowCount = worksheet.Dimension.Rows;
- int ColCount = worksheet.Dimension.Columns;
- bool bHeaderRow = true;
- for (int row = 1; row <= rowCount; row++)
- {
- for (int col = 1; col <= ColCount; col++)
- {
- if (bHeaderRow)
- {
- sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
- }
- else
- {
- sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
- }
- }
- sb.Append(Environment.NewLine);
- }
- return sb.ToString();
- }
- }
- catch (Exception ex)
- {
- return "Some error occured while importing." + ex.Message;
- }
- }
此时我们再来对导入进行统一封装下,如下:
- [HttpGet]
- [Route("Import")]
- public void Import()
- {
- string sWebRootFolder = _hostingEnvironment.WebRootPath;
- string sFileName = @"Jeffcky.xlsx";
- FileStream fs = new FileStream(Path.Combine(sWebRootFolder, sFileName), FileMode.Open, FileAccess.Read, FileShare.Read);
- var list = _ImportManager.ImportPersonFromXlsx(fs);
- }
导入大概就介绍完毕了,要我说真正的难点不在于利用 EPPlus 导入和导出,难点在于批量导入,批量进行导入后对数据格式的检验,如果给定一个导入模板,然后再导入批量数据怎么确保用户给的数据格式完全是正确的以及数据没有重复的校验,这两天基本上是完成了批量的导入,大概分为:数据必填项的校验、数据格式的校验、数据库是否存在数据的校验、数据导入部分导入失败返回格式的用户体验。当利用 NPOI、EPPlus 来导入和导出这样的功能再简单不过了,但是如果遇到了不同的场景怎么让用户体验更好的使用这是一个问题,如果数据导入失败我们怎么去提示用户呢,还有如果 Excel 中有下拉框和合并的单元格数据我们怎么去获取这又是一个问题,可能很多简历上写着会利用 NPOI 和 EPPlus 的导入和导出,其实没什么看头,二者不过是一个工具罢了,如何利用工具去应用到复杂的场景并举例那才算是高级的东西。
本节我们稍微介绍了. net core 中的下载、导入和导出,如果有可能的话后续会给出关于 EPPlus 中高级的知识,比如如上提出的获取合并列数据还有获取图片等等,我们下节再会,哦,关于 SQL Server 有时间会定期进行更新,see u。
来源: http://www.cnblogs.com/CreateMyself/p/6464199.html