选择 100 张图像时,IFormFileCollection 为 NULL

问题描述 投票:0回答:1

为什么在 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; }
}
c# asp.net-core-mvc iformfile iformfilecollection
1个回答
1
投票

为什么回发到控制器时 IFormFileCollection 为 NULL C# 和 ASP.NET Core MVC 中的操作?

根据您的场景和描述以及共享代码片段,您遇到的问题与 ASP.NET Core 中的默认文件上传大小限制有关。默认请求限制 (

maxAllowedContentLength
) 为 30,000,000 字节,这大约是
28.6 MB

您可能知道,当我们从视图向控制器提交请求时,请求最终会从托管服务器 IIS 或 Kestrel Web 服务器进行处理。 这是要点,因为两台服务器都有默认的请求限制,因此包含超过限制的请求将以空请求结束。您可以检查IISKestrel文档

如果我选择 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;
但请记住,也存在服务器超时问题。因此,在延长限制的同时,请考虑到这一点。

如果您想查看更多示例,请参考此官方文档

© www.soinside.com 2019 - 2024. All rights reserved.