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;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。




本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/6464199.html,如需转载请自行联系原作者

目录
相关文章
|
26天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
42 5
|
3月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
103 0
|
2月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
49 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
1月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
28 3
|
11天前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
27 0
|
3月前
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
40 1
|
4月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
4月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
118 3
|
3月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
4月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
87 0