tft每日頭條

 > 科技

 > asp.netcore深入淺出

asp.netcore深入淺出

科技 更新时间:2024-07-31 22:13:38

一般在做應用系統過程中,很多時候會涉及到文件上傳,那麼,我們該如何接收前端傳過來的文件,以及如何保存接收到的文件呢?這一節,我們繼續跟着官網的内容來學習一下。

在我們接收到文件後,文件的存儲位置一般就數據庫、自建存儲、收費雲存儲。那麼自建存儲一般就是單機存儲、共享存儲、基于開源系統搭建分布式存儲。存儲方式不是這一小節的重點,暫不展開讨論。我們繼續回到主題。

通過IFormFile接收文件

在ASP.NET Core6.0中, 支持使用緩沖的模型綁定(針對較小文件)和無緩沖的流式傳輸(針對較大文件)上傳一個或多個文件。模型綁定則是基于IFormFile接口實現,一般有以下幾種用法:

  • 單個 IFormFile
  • IFormFileCollection 多文件集合
  • IEnumerable 多文件
  • 列表 如:List

我們新建一個FileController來演示服務端接收文件的示例,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

[Route("api/[controller]")] [ApiController] public class FileController : ControllerBase { private readonly IWebHostEnvironment _environment; public FileController(IWebHostEnvironment environment) { this._environment = environment; } [HttpPost("/upload")] public async Task<IActionResult> UploadFileAsync(IFormFile file) { var fileName = Path.GetRandomFileName() Path.GetExtension(file.FileName); //拼接完整的文件存儲路徑 var filePath = Path.Combine(_environment.ContentRootPath, fileName); using (var fs = System.IO.File.Create(filePath)) { await file.CopyToAsync(fs); } return Ok(new { Msg = "上傳成功", Code = 200, FileName = fileName }); } }

編寫好代碼後,我們運行起來,通過POSTMAN來測試一下文件上傳功能。在POSTMAN中,我們選中form-data的方式,所以,一定要注意KEY的值要和參數名匹配

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)1

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)2

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)3

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)4

此時,我們能看到上傳的文件已保存到指定的目錄中

我們再來試試多文件上傳,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

[HttpPost("multi-upload")] public async Task<IActionResult> MultiUploadFileAsync(List<IFormFile> files) { long size = files.Sum(f => f.Length); List<string> fileNames = new List<string>(); foreach (var file in files) { var fileName = Path.GetRandomFileName() Path.GetExtension(file.FileName); //拼接完整的文件存儲路徑 var filePath = Path.Combine(_environment.ContentRootPath, fileName); fileNames.Add(fileName); using (var fs = System.IO.File.Create(filePath)) { await file.CopyToAsync(fs); } } return Ok(new { Msg = "上傳成功", Code = 200, FileNames = fileNames, TotalSize = size }); }

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)5

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)6

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)7

使用 IFormFile 上傳的文件在處理之前會緩沖在内存中或服務器的磁盤中,如果文件過大的話,會對内存造成比較大的影響。在大文件的情況下,我們需要了解一下文件流方式,這個就後面用到時候的時候再說吧。接下來,我們就繼續了解一下上傳文件時的文件安全處理方式,不排除有不法分子上傳一些病毒或者腳本之類的東西來破壞我們的服務器。當然,如果是用的收費的OSS則不需要考慮這種情況了。

文件擴展名驗證

一般,我們需要限制上傳文件的類型,這樣一來,我們可以排除掉一些風險,思路是我們可以通過校驗上傳的文件後綴來初步判斷上傳的是否符合我們要求的合規文件,如:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

public class FileController : ControllerBase { private readonly IWebHostEnvironment _environment; private readonly string[] permittedExtensions = { ".txt", ".pdf",".docx" }; public FileController(IWebHostEnvironment environment) { this._environment = environment; } [HttpPost("upload")] public async Task<IActionResult> UploadFileAsync([FromForm] IFormFile file) { var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext)) { return BadRequest(); } var fileName = Path.GetRandomFileName() Path.GetExtension(file.FileName); //拼接完整的文件存儲路徑 var filePath = Path.Combine(_environment.ContentRootPath, fileName); using (var fs = System.IO.File.Create(filePath)) { await file.CopyToAsync(fs); } return Ok(new { Msg = "上傳成功", Code = 200, FileName = fileName }); } }

我們先嘗試上傳一個txt文件

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)8

可以看到,文件上傳成功。在嘗試上傳一個zip文件。

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)9

服務端直接就報400錯誤。

文件簽名驗證

文件的簽名由文件開頭部分中的前幾個字節确定。 可以使用這些字節指示擴展名是否與文件内容匹配。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

[Route("api/[controller]")] [ApiController] public class FileController : ControllerBase { private readonly IWebHostEnvironment _environment; private readonly string[] permittedExtensions = { ".txt", ".pdf", ".docx" }; private static readonly Dictionary<string, List<byte[]>> _fileSignature = new Dictionary<string, List<byte[]>> { { ".pdf", new List<byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } }, { ".docx", new List<byte[]> { new byte[] { 0x50 ,0x4B ,0x03, 0x04 }, new byte[] { 0x50, 0x4B , 0x03 , 0x04 , 0x14 , 0x00 , 0x06 , 0x00 } } }, }; public FileController(IWebHostEnvironment environment) { this._environment = environment; } [HttpPost("upload")] public async Task<IActionResult> UploadFileAsync([FromForm] IFormFile file) { var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext)) { return BadRequest(); } using (var reader = new BinaryReader(file.OpenReadStream())) { var signatures = _fileSignature[ext]; var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length)); if (!signatures.Any(signature => headerBytes.Take(signature.Length).SequenceEqual(signature))) { return BadRequest(new { Msg="文件有誤"}); } } var fileName = Path.GetRandomFileName() Path.GetExtension(file.FileName); //拼接完整的文件存儲路徑 var filePath = Path.Combine(_environment.ContentRootPath, fileName); using (var fs = System.IO.File.Create(filePath)) { await file.CopyToAsync(fs); } return Ok(new { Msg = "上傳成功", Code = 200, FileName = fileName }); } } }

我先上傳一個标準的pdf文件,

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)10

可以看到,是能正常上傳的,我把一個txt文件後綴直接改為pdf,然後再進行上傳。

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)11

可以看到,我們的文件簽名無法校驗通過

文件名安全

如果我們取用客戶端的文件名進行存儲的話,很容易因為文件名重複而導緻文件被覆蓋。所以,官方建議:切勿使用客戶端提供的文件名來将文件保存到物理存儲

文件大小限制

在Kestrel和IIS的請求正文中,默認的最大請求正文大小為 30,000,000 個字節,約為 28.6 MB。我上傳一個98.6M的大文件,看看服務端的反應

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)12

這裡我們使用的是Kestrel,可以直接到Program.cs中進行配置

1 2 3

builder.WebHost.ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 524288000; });

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)13

此時,大文件便可上傳,上面的配置是全局配置,我們也可以在單個文件接口通過RequestSizeLimitAttribute屬性來達到目的,如:

1

[RequestSizeLimit(524288000)]

asp.netcore深入淺出(跟着官網學ASP.NETCore6.0之文件上傳)14

ASP.NET Core 6.0上傳文件的内容,我們就先暫時了解到這裡吧,以後在實踐過程中有遇到難題事再進行深究。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved