为什么在 C# 和 ASP.NET Core MVC 中回发到控制器操作时
IFormFileCollection
为 NULL?
如果我选择 10 张图像,它会起作用,如果我选择 100 张图像,它会失败 - 为什么? IFormFileCollection 有文件上传限制吗?
这是代码 - 控制器/操作:
using Microsoft.AspNetCore.Mvc;
using IFormFileCollectionImageUploadTest.Models;
namespace IFormFileCollectionImageUploadTest.Controllers;
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Upload(IFormFileCollection images)
{
var resultsViewModel = new ResultsViewModel();
if (images != null && images.Count > 0)
{
resultsViewModel.Message = $"IFormFileCollection is NOT NULL, with image count of {images.Count}!";
}
else
{
resultsViewModel.Message = $"IFormFileCollection is NULL with image count of ZERO!";
}
return RedirectToAction("Results", "Home", resultsViewModel);
}
[HttpGet]
public IActionResult Results(ResultsViewModel resultsViewModel)
{
return View(resultsViewModel);
}
}
索引视图:
@using IFormFileCollectionImageUploadTest.Models;
@model ImageUploadViewModel
@{
ViewBag.Title = "Upload Images";
}
<style type="text/css">
.btn-file-display {
display: none;
}
.btn-file {
position: relative;
overflow: hidden;
}
.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;
}
</style>
<div class="row">
<div class="col-md-4 col-12 mx-auto">
<h2 class="text-center">@ViewBag.Title</h2>
<p class="text-center">Select multiple images,<br />to upload more than one image at once</p>
<div class="card card-pricing card-raised">
<div class="card-body">
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { @enctype = "multipart/form-data", @class = "form-horizontal", @role = "form" }))
{
@Html.AntiForgeryToken();
<div class="row">
<div class="col-12">
<label class="btn btn-block btn-outline-primary">
Browse...
@Html.TextBoxFor(model => model.Images, "", new { @class = "btn-file-display", @type = "file", @multiple = "multiple" })
</label>
@Html.ValidationMessageFor(model => model.Images, "", new { @class = "text-danger" })
<p id="selectedImageFiles" class="text-success text-center"></p>
</div>
</div>
<div class="row">
<div class="col-12">
<button class="btn btn-success btn-lg btn-block">Upload</button>
</div>
</div>
<div class="row">
<div class="col-12">
<p class="text-info">@ViewBag.UploadStatus</p>
</div>
</div>
}
</div>
</div>
</div>
</div>
@section scripts
{
<script type="text/javascript">$(document).on('change', ':file', function () {
var input = $(this),
numFiles = input.get(0).files ? input.get(0).files.length : 1,
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
input.trigger('fileselect', [numFiles, label]);
});
$(document).ready(function () {
$(':file').on('fileselect', function (event, numFiles, label) {
if (numFiles == 1) {
$('#selectedImageFiles').text(numFiles + " image chosen for upload");
}
else {
$('#selectedImageFiles').text(numFiles + " images chosen for upload");
}
console.log(numFiles);
console.log(label);
});
});</script>
}
结果查看:
@model ResultsViewModel
<div class="text-center">
@Model.Message
</div>
上传视图模型:
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
namespace IFormFileCollectionImageUploadTest.Models;
public class ImageUploadViewModel
{
[Required(ErrorMessage = "Please select images")]
public IFormFileCollection[] Images { get; set; }
}
结果视图模型:
namespace IFormFileCollectionImageUploadTest.Models;
public class ResultsViewModel
{
public string Message { get; set; }
}
为什么回发到控制器时 IFormFileCollection 为 NULL C# 和 ASP.NET Core MVC 中的操作?
根据您的场景和描述以及共享代码片段,您遇到的问题与 ASP.NET Core 中的默认文件上传大小限制有关。默认请求限制 (
maxAllowedContentLength
) 为 30,000,000 字节,这大约是28.6 MB
。
您可能知道,当我们从视图向控制器提交请求时,请求最终会从托管服务器 IIS 或 Kestrel Web 服务器进行处理。 这是要点,因为两台服务器都有默认的请求限制,因此包含超过限制的请求将以空请求结束。您可以检查IIS和Kestrel文档。
如果我选择 10 张图像,它会起作用,如果我选择 100 张图像,它会失败 - 为什么?是 IFormFileCollection 有文件上传限制吗?
它不是 IFormFileCollection,但在 ASP.NET Core 或 IIS 中,有一个默认的请求限制,但我们可以自定义它们以上传更大的文件。它可以通过增加program.cs文件配置中的MultipartBodyLengthLimit属性大小来处理,或者我们可以将大型上传分成较小的块或使用分块库。甚至,您也可以压缩上传的文件。
但是,我更热衷于在program.cs文件中增加
MultipartBodyLengthLimit
。如果你愿意也可以尝试其他方法。
让我们看看如何实现它。
在Program.cs文件中自定义请求限制:
builder.Services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 52428800;
});
注意:我目前设置为50MB。如果你想设置得更高,你可以这样做。对于 100MB,您可以做到
100 * 1024 * 1024;
但请记住,也存在服务器超时问题。因此,在延长限制的同时,请考虑到这一点。
如果您想查看更多示例,请参考此官方文档。