zoukankan      html  css  js  c++  java
  • ASP.NET Core MVC上传、导入、导出知多少

     

     

    前言

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

    .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 来接收,该接口定义如下:

    复制代码
    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<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方法用渲染的方式,如下:

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

    当然别忘记添加TagHelper:

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

    成功上传我们显示上传字节大小,如下:

    上传的文件在网站根目录下我们能够看到,如下:

    上述我们只是牛刀小试通过表单提交,接下来我们进行拓展通过Ajax来提交。我们将表单类型submit修改为button,如下:

    复制代码
             <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;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() + "	");
                                }
                                else
                                {
                                    sb.Append(worksheet.Cells[row, col].Value.ToString() + "	");
                                }
                            }
                            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的导入和导出,其实没什么看头,二者不过是一个工具罢了,如何利用工具去应用到复杂的场景并举例那才算是高级的东西。

     

  • 相关阅读:
    布局重用 include merge ViewStub
    AS 常用插件 MD
    AS 2.0新功能 Instant Run
    AS .ignore插件 忽略文件
    AS Gradle构建工具与Android plugin插件【大全】
    如何开通www国际域名个人网站
    倒计时实现方案总结 Timer Handler
    AS 进行单元测试
    RxJava 设计理念 观察者模式 Observable lambdas MD
    retrofit okhttp RxJava bk Gson Lambda 综合示例【配置】
  • 原文地址:https://www.cnblogs.com/deepalley/p/14546181.html
Copyright © 2011-2022 走看看