使用 HTTP 協議上傳文件的標準做法是:使用?multipart/form-data
?。但有時為了實現簡單且要上傳的文件不會太大,仍然會采用?application/x-www-form-urlencoded
?上傳文件,這就需要在上傳前對二進制文件進行編碼,比如使用 Base64 。
public async Task<IActionResult> SubmitImage(int id, [FromForm(Name = "image")] string image)
{if (string.IsNullOrWhiteSpace(image)) throw new UserFriendlyException("圖片不能為空");var data = Convert.FromBase64String(image);//TODO:處理圖片
}
以上代碼一直工作良好,很久以后接到客戶反饋有幾張圖片一直上傳失敗,明明選擇了圖片卻還是提示“圖片不能為空”。這說明 image 參數沒有被正確綁定上。圖片的大小為 6MB 左右,這很顯然沒有突破 IIS 的限制(默認為 30MB),也沒有突破 ASP.NET Ccor 對單個請求大小的限制(默認為 30MB)。我特意去查看了 Windows 日志,也沒有看到報錯信息。
模擬用戶的請求,確實在 HTTP 抓包中看到了圖片,但是調試器中 image 確實為空。幾番搜索下來,我找到了一個名為?FormOptions
?的配置類:
https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.http.features.formoptions?view=aspnetcore-6.0
其中的?ValueLengthLimit
?屬性有如下定義:
A limit on the length of individual form values. Forms containing values that exceed this limit will throw an InvalidDataException when parsed. Defaults to 4,194,304 bytes?, which is approximately 4MB.
也就是說:默認情況下,ASP.NET Core 限制了每個 POST 數據值的長度為 4 MB 大小,超過就會拋出?InvalidDataException
?異常。我很可能是遇到了這個限制,但因為并沒有拋異常所以不太敢確定。
services.Configure<FormOptions>(options=>{options.ValueLengthLimit = 209715200;//200MB
});
以上代碼將限制提升到了 200MB,經測試問題解決。
使用 Base64 將文件編碼后雖然會簡化,但同時會導致網絡傳輸內容增大,或者遇到本文所示的異常(默認情況下,multipart/form-data
?對單個上傳項的限制是 128MB)。如果你使用的是 MVC,也可以直接使用?RequestFormLimitsAttribute
?解決該問題:
https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.requestformlimitsattribute?view=aspnetcore-6.0