使用NetCore 3.0怎么實現(xiàn)大文件上傳限制功能?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

NetCore文件上傳兩種方式
NetCore官方給出的兩種文件上傳方式分別為“緩沖”、“流式”。我簡單的說說兩種的區(qū)別,
1.緩沖:通過模型綁定先把整個文件保存到內(nèi)存,然后我們通過IFormFile得到stream,優(yōu)點是效率高,缺點對內(nèi)存要求大。文件不宜過大。
2.流式處理:直接讀取請求體裝載后的Section 對應的stream 直接操作strem即可。無需把整個請求體讀入內(nèi)存,
以下為官方微軟說法
緩沖
整個文件讀入 IFormFile,它是文件的 C# 表示形式,用于處理或保存文件。 文件上傳所用的資源(磁盤、內(nèi)存)取決于并發(fā)文件上傳的數(shù)量和大小。 如果應用嘗試緩沖過多上傳,站點就會在內(nèi)存或磁盤空間不足時崩潰。 如果文件上傳的大小或頻率會消耗應用資源,請使用流式傳輸。
流式處理
從多部分請求收到文件,然后應用直接處理或保存它。 流式傳輸無法顯著提高性能。 流式傳輸可降低上傳文件時對內(nèi)存或磁盤空間的需求。
文件大小限制
說起大小限制,我們得從兩方面入手,1應用服務器Kestrel 2.應用程序(我們的netcore程序),
1.應用服務器Kestre設置
應用服務器Kestrel對我們的限制主要是對整個請求體大小的限制通過如下配置可以進行設置(Program -> CreateHostBuilder),超出設置范圍會報BadHttpRequestException: Request body too large異常信息
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel((context, options) =>
{
//設置應用服務器Kestrel請求體較大為50MB
options.Limits.MaxRequestBodySize = 52428800;
});
webBuilder.UseStartup<Startup>();
});2.應用程序設置
應用程序設置 (Startup-> ConfigureServices) 超出設置范圍會報InvalidDataException 異常信息
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = long.MaxValue;
});通過設置即重置文件上傳的大小限制。
源碼分析
這里我主要說一下 MultipartBodyLengthLimit 這個參數(shù)他主要限制我們使用“緩沖”形式上傳文件時每個的長度。為什么說是緩沖形式中,是因為我們緩沖形式在讀取上傳文件用的幫助類為 MultipartReaderStream 類下的 Read 方法,此方法在每讀取一次后會更新下讀入的總byte數(shù)量,當超過此數(shù)量時會拋出 throw new InvalidDataException($"Multipart body length limit {LengthLimit.GetValueOrDefault()} exceeded."); 主要體現(xiàn)在 UpdatePosition 方法對 _observedLength 的判斷
以下為 MultipartReaderStream 類兩個方法的源代碼,為方便閱讀,我已精簡掉部分代碼
Read
public override int Read(byte[] buffer, int offset, int count)
{
var bufferedData = _innerStream.BufferedData;
int read;
read = _innerStream.Read(buffer, offset, Math.Min(count, bufferedData.Count));
return UpdatePosition(read);
}UpdatePosition
private int UpdatePosition(int read)
{
_position += read;
if (_observedLength < _position)
{
_observedLength = _position;
if (LengthLimit.HasValue && _observedLength > LengthLimit.GetValueOrDefault())
{
throw new InvalidDataException($"Multipart body length limit {LengthLimit.GetValueOrDefault()} exceeded.");
}
}
return read;
}通過代碼我們可以看到 當你做了 MultipartBodyLengthLimit 的限制后,在每次讀取后會累計讀取的總量,當讀取總量超出
MultipartBodyLengthLimit 設定值會拋出 InvalidDataException 異常,
最終我的文件上傳Controller如下
需要注意的是我們創(chuàng)建 MultipartReader 時并未設置 BodyLengthLimit (這參數(shù)會傳給MultipartReaderStream.LengthLimit )也就是我們最終的限制,這里我未設置值也就無限制,可以通過 UpdatePosition 方法體現(xiàn)出來
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers;
using System.IO;
using System.Threading.Tasks;
namespace BigFilesUpload.Controllers
{
[Route("api/[controller]")]
public class FileController : Controller
{
private readonly string _targetFilePath = "C:\\files\\TempDir";
/// <summary>
/// 流式文件上傳
/// </summary>
/// <returns></returns>
[HttpPost("UploadingStream")]
public async Task<IActionResult> UploadingStream()
{
//獲取boundary
var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
//得到reader
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
//{ BodyLengthLimit = 2000 };//
var section = await reader.ReadNextSectionAsync();
//讀取section
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
var trustedFileNameForFileStorage = Path.GetRandomFileName();
await WriteFileAsync(section.Body, Path.Combine(_targetFilePath, trustedFileNameForFileStorage));
}
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileController), null);
}
/// <summary>
/// 緩存式文件上傳
/// </summary>
/// <param name=""></param>
/// <returns></returns>
[HttpPost("UploadingFormFile")]
public async Task<IActionResult> UploadingFormFile(IFormFile file)
{
using (var stream = file.OpenReadStream())
{
var trustedFileNameForFileStorage = Path.GetRandomFileName();
await WriteFileAsync(stream, Path.Combine(_targetFilePath, trustedFileNameForFileStorage));
}
return Created(nameof(FileController), null);
}
/// <summary>
/// 寫文件導到磁盤
/// </summary>
/// <param name="stream">流</param>
/// <param name="path">文件保存路徑</param>
/// <returns></returns>
public static async Task<int> WriteFileAsync(System.IO.Stream stream, string path)
{
const int FILE_WRITE_SIZE = 84975;//寫出緩沖區(qū)大小
int writeCount = 0;
using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write, FILE_WRITE_SIZE, true))
{
byte[] byteArr = new byte[FILE_WRITE_SIZE];
int readCount = 0;
while ((readCount = await stream.ReadAsync(byteArr, 0, byteArr.Length)) > 0)
{
await fileStream.WriteAsync(byteArr, 0, readCount);
writeCount += readCount;
}
}
return writeCount;
}
}
}看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)網(wǎng)站建設公司,的支持。
本文名稱:使用NetCore3.0怎么實現(xiàn)大文件上傳限制功能-創(chuàng)新互聯(lián)
網(wǎng)站網(wǎng)址:http://www.chinadenli.net/article24/dcppje.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導航、網(wǎng)站設計公司、App開發(fā)、網(wǎng)站制作、品牌網(wǎng)站設計、手機網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)