学海无涯

导航

上传文件 FileUpload

ASP.NET Core 支持使用缓冲的模型绑定(针对较小文件)和无缓冲的流式传输(针对较大文件)上传一个或多个文件。

文件上传方案

缓冲和流式传输是上传文件的两种常见方法。

缓冲

如果文件上传的大小或频率会消耗应用资源,请使用流式传输。

流式处理

流式传输无法显著提高性能。 流式传输可降低上传文件时对内存或磁盘空间的需求。

通过缓冲的模型绑定将小型文件上传到物理存储

上传到服务器的单个文件可使用 IFormFile 接口通过模型绑定进行访问。

使用模型绑定和 IFormFile 上传文件时,操作方法可以接受以下内容:

appsetting.json 配置参数

  "StoredFilesPath": "Images",
  "FileSizeLimit": 2097152

  

using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Protocols;
using MvcMovie.Data;
using MvcMovie.Models;
using MvcMovie.ViewModels;
using static System.Net.Mime.MediaTypeNames;

namespace MvcMovie.Controllers;
public class FileUploadController : Controller
{
    IWebHostEnvironment _host;
    IConfiguration _config;
    MvcMovieContext _dbContext;
    string _storedFilesPath = string.Empty;//上传文件目录
    readonly long _fileSizeLimit;//文件大小限制

    public FileUploadController(IWebHostEnvironmenthost, IConfiguration config, MvcMovieContext dbContext)
    {
        _host = host;
        _config = config;
        _storedFilesPath = Path.Combine(_host.WebRootPath,
       _config["StoredFilesPath"]);
        _fileSizeLimit = _config.GetValue<long>("FileSizeLimit");
        _dbContext = dbContext;
    }

    public IActionResult Index()
    {
        return View();
    }
    //上传单个文件
    [HttpPost]
    public async Task<IActionResult> Upload(FileUpload fileUpload)
    {
        long size = fileUpload.FormFile.Length;

        if (size > 0)
        {

            //          var filePath = Path.Combine(_storedFilesPath,
            //Path.GetRandomFileName());
            var filePath = Path.Combine(_storedFilesPath, GenerateFileName(fileUpload.FormFile.FileName));

            using (var stream = System.IO.File.Create(filePath))
            {
                await fileUpload.FormFile.CopyToAsync(stream);
            }
        }
        return RedirectToAction("Index");
    }

    public IActionResult UploadMultiple()
    {
        return View();
    }
    //上传多个文件
    [HttpPost]
    public async Task<IActionResult> UploadMultiple(FileUpload fileUpload)
    {
        long size = fileUpload.FormFiles.Sum(f => f.Length);

        foreach (var formFile in fileUpload.FormFiles)
        {
            if (formFile.Length > 0)
            {

                var filePath = Path.Combine(_storedFilesPath,
        Path.GetRandomFileName());

                using (var stream = System.IO.File.Create(filePath))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }

        // Process uploaded files
        // Don't rely on or trust the FileName property without validation.

        var count = (new { count = fileUpload.FormFiles.Count, size });

        return RedirectToAction("Index");
    }

    public IActionResult UploadDb()
    {
        return View();
    }
    //上传文件到数据库中的byte[]字段
    [HttpPost]
    public async Task<IActionResult> UploadDb(BufferedSingleFileUploadDbViewModel viewModel)
    {
        if (viewModel == null || viewModel.FormFile == null)
        {
            ModelState.AddModelError("", "请选择一个文件。");
            return View();
        }
        if (!ValidFileExtension(viewModel.FormFile.FileName))
        {
            ModelState.AddModelError("", "不支持的文件类型。");
            return View();
        }
        using (var memoryStrema = new MemoryStream())
        {
            await viewModel.FormFile.CopyToAsync(memoryStrema);
            //仅能上传文件小于2MB
            if (memoryStrema.Length < _fileSizeLimit)
            {
                var file = new AppFile
                {
                    Content = memoryStrema.ToArray()
                };
                _dbContext.appFiles.Add(file);
                await _dbContext.SaveChangesAsync();
            }
            else
            {
                ModelState.AddModelError("", "上传文件大不能超过2M。");
                return View();
            }
        }
        return RedirectToAction("Index");
    }
    /// <summary>
    /// 文件扩展名验证
    /// </summary>
    /// <param name="uploadedFileName">上传文件名</param>
    /// <returns></returns>
    private bool ValidFileExtension(string uploadedFileName)
    {
        string[] permittedExtensions = { ".txt", ".pdf", ".doc" };

        var ext = Path.GetExtension(uploadedFileName).ToLowerInvariant();

        if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext))
        {
            return false;
        }
        return true;
    }
    /// <summary>
    /// 生成文件名
    /// </summary>
    /// <param name="uploadedFileName"></param>
    /// <returns></returns>
    private string GenerateFileName(string uploadedFileName)
    {
        string fileName = Guid.NewGuid().ToString();
        fileName = $"{fileName}{Path.GetExtension(uploadedFileName)}";
        return fileName;
    }
}
public class FileUpload
    {
        public IFormFile FormFile { get; set; }
        public List<IFormFile> FormFiles { get; set;}
    }

 一、上传单个文件 

@model FileUpload
<h3>上传单个文件</h3>
<form enctype="multipart/form-data" asp-action="Upload" method="post">
    <dl>
        <dt>
            <label asp-for="FormFile"></label>
        </dt>
        <dd>
            <input asp-for="FormFile" type="file" />
            <span asp-validation-for="FormFile"></span>
        </dd>
    </dl>
    <input class="btn btn-primary" type="submit" value="Upload" />
</form>

<a asp-action="UploadMultiple">上传多个文件</a>
<a asp-action="UploadDb">上传文件到数据库</a>

 二、上传多个文件

@model FileUpload

<h2>一次选择多个文件上传</h2>

<form enctype="multipart/form-data" asp-action="UploadMultiple" method="post">
    <dl>
        <dt>
            <label asp-for="FormFiles"></label>
        </dt>
        <dd>
            <input asp-for="FormFiles" type="file" multiple />
            <span asp-validation-for="FormFiles"></span>
        </dd>
    </dl>
    <input class="btn btn-primary" type="submit" value="Upload" />
</form>

三、上传文件到数据库

public class AppFile
    {
        public int Id { get; set; }
        public byte[] Content { get; set; }
    }

 

  public class BufferedSingleFileUploadDbViewModel
    {
        [Required]
        [Display(Name = "文件")]
        public IFormFile FormFile { get; set; }
    }

 

@model BufferedSingleFileUploadDbViewModel
<h3>上传文件到数据库</h3>
<form enctype="multipart/form-data" asp-action="UploadDb" method="post">
    <dl>
        <dt>
            <label asp-for="FormFile"></label>
        </dt>
        <dd>
            <input asp-for="FormFile" type="file" />
            <span asp-validation-for="FormFile"></span>
        </dd>
    </dl>
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input class="btn btn-primary" type="submit" value="Upload" />
</form> 

服务器和应用程序配置

多部分正文长度限制

MultipartBodyLengthLimit 设置每个多部分正文的长度限制。 分析超出此限制的窗体部分时,会引发 InvalidDataException。 默认值为 134,217,728 (128 MB)。 使用 Startup.ConfigureServices 中的 MultipartBodyLengthLimit 设置自定义此限制:

 

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<FormOptions>(options =>
    {
        // Set the limit to 256 MB
        options.MultipartBodyLengthLimit = 268435456;
    });
}

在 Razor Pages 应用或 MVC 应用中,将筛选器应用到页面模型或操作方法:

// Set the limit to 256 MB
[RequestFormLimits(MultipartBodyLengthLimit = 268435456)]
public class BufferedSingleFileUploadPhysicalModel : PageModel
{
    ...
}

参考:https://learn.microsoft.com/zh-cn/aspnet/core/mvc/models/file-uploads?view=aspnetcore-7.0

 

posted on 2023-02-19 17:27  宁静致远.  阅读(119)  评论(0编辑  收藏  举报