.net core 上传大文件

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using DiuDiuTemplate.Domain.WebHelpers.Base;
using DiuDiuTemplate.Infrastructure.Common.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers;

namespace DiuDiuTemplate.UserApi.Controllers
{
    public class FileUpLoadController : ApiControllerBase
    {
        private IWebHostEnvironment _webhostEnv;

        public FileUpLoadController(IWebHostEnvironment webhostEnv)
        {
            _webhostEnv = webhostEnv;
        }

        /// <summary>
        /// 上传文件到API服务器 较小的文件上传 20M
        /// </summary>
        /// <returns>返回文件的saveKeys</returns>
        [HttpPost]
        [RequestSizeLimit(20971520)]
        [AllowAnonymous]
        public async Task<List<string>> UploadFile(List<IFormFile> files)
        {
            List<string> saveKeys = new List<string>();

            foreach (var formFile in files)
            {
                //相对路径
                string saveKey = GetRelativePath(formFile.FileName);

                //完整路径
                string path = GetAbsolutePath(saveKey);
                await WriteFileAsync(formFile.OpenReadStream(), path);
                saveKeys.Add(saveKey);
            }
            return saveKeys;
        }
        /// <summary>
        /// 大文件上传到API服务器
        /// 流式接收文件,不缓存到服务器内存/// </summary>
        /// <att name="DisableRequestSizeLimit">不限制请求的大小</att>
        /// <returns>返回文件的saveKeys</returns>
        [HttpPost]
        [Route("BigFileUpload")]
        [DisableRequestSizeLimit]
        [AllowAnonymous]
        public async Task<List<string>> BigFileUpload()
        {
            List<string> saveKeys = new List<string>();

            //获取boundary
            var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
            //得到reader
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);
             
            var section = await reader.ReadNextSectionAsync();

            //读取 section  每个formData算一个 section  多文件上传时每个文件算一个 section
            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                if (hasContentDispositionHeader)
                {
                    if (contentDisposition.IsFileDisposition())
                    {
                        //相对路径
                        string saveKey = GetRelativePath(contentDisposition.FileName.Value);
                        //完整路径
                        string path = GetAbsolutePath(saveKey);

                        await WriteFileAsync(section.Body, path);
                        saveKeys.Add(saveKey);
                    }
                    else
                    {
                        string str = await section.ReadAsStringAsync();
                    }
                }
                section = await reader.ReadNextSectionAsync();
            }
            return saveKeys;

        }
        /// <summary>
        /// 写文件导到磁盘
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="path">文件保存路径</param>
        /// <returns></returns>
        private static async Task<int> WriteFileAsync(System.IO.Stream stream, string path)
        {
            const int FILE_WRITE_SIZE = 84975;//写出缓冲区大小
            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;
        }

        /// <summary>
        /// 获取相对路径
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private string GetRelativePath(string fileName)
        {
            string str1 = CommonHelper.GetGuid().Replace("-", "");
            int start = fileName.LastIndexOf('.');
            //相对路径
            return $"/upload/{DateTime.Now.Year}/{DateTime.Now.Month}/{DateTime.Now.Day}/{str1}{fileName.Substring(start, fileName.Length - start)}";

        }
        /// <summary>
        /// 获取完整路径
        /// </summary>
        /// <param name="relativePath"></param>
        /// <returns></returns>
        private string GetAbsolutePath(string relativePath)
        {
            //完整路径
            string path = Path.Join(_webhostEnv.WebRootPath, relativePath);

            string directoryPath = Path.GetDirectoryName(path);
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            return path;

        }
    }
}

小文件上传和大文件上传;

最后记得要添加静态文件中间件

app.UseStaticFiles();

API默认没有这个中间件

还可以设置一些上传大小的限制,这个只是程序的配置,如果部署到IIS等,还需要修改IIS的上传文件限制,这里只实现代码部分;

  

services.Configure<FormOptions>(x =>
{
  x.ValueLengthLimit = int.MaxValue;
  x.MultipartBodyLengthLimit = int.MaxValue;
  x.MultipartHeadersLengthLimit = int.MaxValue;
});

原文地址:https://www.cnblogs.com/zhanghm1/p/12890815.html