ASP.NET Core MVC上传、导入、导出知多少

前言

本君已成夜猫子,本节咱们来说讲ASP.NET Core MVC中的上传,这两天在研究批量导入功能,本节顺便简单搞搞导入、导出,等博主弄稳当了再来和你们一并分享。ajax

.NET Core MVC上传

首先咱们来看看官网的上传的例子,再而后进行拓展训练,官网的表单是这样的。数据库

<form method="post" enctype="multipart/form-data" asp-controller="UploadFiles" asp-action="Index">
    <div class="form-group">
        <div class="col-md-10">
            <p>Upload one or more files using this form:</p>
            <input type="file" name="files" multiple />
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-10">
            <input type="submit" value="上传" />
        </div>
    </div>
</form>

在ASP.NET Core MVC中接收上传的文件须要用 IFormFile 来接收,该接口定义以下:app

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方法进行以下定义:async

        [HttpPost("UploadFiles")]
        public async Task<IActionResult> Post(List<IFormFile> 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<IFormFile> 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

<form method="post" enctype="multipart/form-data" asp-controller="Upload" asp-action="UploadFiles">
</form>

固然别忘记添加TagHelper:网站

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

成功上传咱们显示上传字节大小,以下:ui

上传的文件在网站根目录下咱们可以看到,以下:this

上述咱们只是牛刀小试经过表单提交,接下来咱们进行拓展经过Ajax来提交。咱们将表单类型submit修改成button,以下:url

         <div class="row">
            <div class="form-group">
                <div class="col-md-10">
                    <p>使用表单上传多个文件</p>
                    <input type="file" id="files" name="files" multiple />
                    @ViewBag.Message
                </div>
            </div>
        </div>
        <div class="row">
            <div class="form-group">
                <div class="col-md-10">
                    <input type="button"  id="upload" class="btn btn-success" style="cursor:pointer;width:100px;" value="上传" />
                </div>
            </div>
        </div>

咱们经过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中的上传就告一段落,仍是比较简单可是算是比较常见的需求。

导入、导出Excel

项目中须要用到批量导入和导出因而进行了一点研究,.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<Person>[]
            {
                new PropertyByName<Person>("Id",d=>d.Id),
                new PropertyByName<Person>("Name",d=>d.Name),
                new PropertyByName<Person>("Age",d=>d.Age)
            };

            var list = new List<Person>()
            {
                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<Person>(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。

相关文章
相关标签/搜索