首頁»ASP.NET»ASP.NET Core MVC上傳、導入、導出知多少

                    ASP.NET Core MVC上傳、導入、導出知多少

                    來源:Jeffcky 發布時間:2017-03-03 閱讀次數:

                     前言

                      本君已成夜貓子,本節我們來講講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 + [email protected]"\{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 + [email protected]"\{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。

                    QQ群:WEB開發者官方群(515171538),驗證消息:10000
                    微信群:加小編微信 849023636 邀請您加入,驗證消息:10000
                    提示:更多精彩內容關注微信公眾號:全棧開發者中心(fsder-com)
                    網友評論(共0條評論) 正在載入評論......
                    理智評論文明上網,拒絕惡意謾罵 發表評論 / 共0條評論
                    登錄會員中心
                    福彩试机号今天