ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NetCore-缓存文件上传和文件流上传

2021-09-22 15:04:32  阅读:230  来源: 互联网

标签:文件 fileNameEx NetCore section var new 上传


NetCore官方给出的两种文件上传方式分别为“缓冲”、“流式”。

1.缓冲处理:

通过模型绑定先把整个文件保存到内存,然后我们通过IFormFile得到stream,优点是效率高,缺点对内存要求大。文件不宜过大。

整个文件读入 IFormFile,它是文件的 C# 表示形式,用于处理或保存文件。 文件上传所用的资源(磁盘、内存)取决于并发文件上传的数量和大小。 如果应用尝试缓冲过多上传,站点就会在内存或磁盘空间不足时崩溃。 如果文件上传的大小或频率会消耗应用资源,请使用流式传输。

 

 

 

 

2.流式处理:

直接读取请求体装载后的Section 对应的stream 直接操作strem即可。无需把整个请求体读入内存

从多部分请求收到文件,然后应用直接处理或保存它。 流式传输无法显著提高性能。 流式传输可降低上传文件时对内存或磁盘空间的需求。

(1)创建FileStreamingHelper 帮助类

 

 相关StreamFile方法:

   public static async Task<MsgDto<string>> StreamFiles(this HttpRequest request, string targetDirectory)

        {

            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))

            {

                throw new Exception($"Expected a multipart request, but got {request.ContentType}");

            }

            var fileName = "";

            // Used to accumulate all the form url encoded key value pairs in the 

            // request.

            var formAccumulator = new KeyValueAccumulator();

            var boundary = MultipartRequestHelper.GetBoundary(

                MediaTypeHeaderValue.Parse(request.ContentType),

                _defaultFormOptions.MultipartBoundaryLengthLimit);

            var reader = new MultipartReader(boundary, request.Body);

            var filecanvsname = "";

            var itemindex = 1;

            var filesection = await reader.ReadNextSectionAsync();//用于读取Http请求中的第一个section数据

            var items = new List<string>();

            while (filesection != null)//遍历

            {

                ContentDispositionHeaderValue contentDisposition;

                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(filesection.ContentDisposition, out contentDisposition);

                /*

                   用于处理表单键值数据的section

                   -----------------------------99614912995

                   Content - Disposition: form - data; name = "SOMENAME"

 

                   Formulaire de Quota

                   -----------------------------99614912995

                   */

                //字符格式

                if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))

                {

                    // Content-Disposition: form-data; name="key"

                    //

                    // value

                    // Do not limit the key name length here because the 

                    // multipart headers length limit is already in effect.

                    var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);

                    var encoding = GetEncoding(filesection);

                    using (var streamReader = new StreamReader(

                        filesection.Body,

                        encoding,

                        detectEncodingFromByteOrderMarks: true,

                        bufferSize: 1024,

                        leaveOpen: true))

                    {

                        // The value length limit is enforced by MultipartBodyLengthLimit

                        var value = await streamReader.ReadToEndAsync();

                        if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))

                        {

                            value = String.Empty;

                        }

                        formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key

                        filecanvsname = value;

                        Log4netHelper.Write("StreamFiles:(Value)" + value);

                        if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)

                        {

                            throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");

                        }

                    }

                }

                //文件格式

                else if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))

                {

                       /*

                        用于处理上传文件类型的的section

                        -----------------------------99614912995

                        Content - Disposition: form - data; name = "files"; filename = "Misc 002.jpg"

 

                        ASAADSDSDJXCKDSDSDSHAUSAUASAASSDSDFDSFJHSIHFSDUIASUI+/==

                        -----------------------------99614912995

                    */

                    if (!Directory.Exists(targetDirectory))

                    {

                        Directory.CreateDirectory(targetDirectory);

                    }

                    Log4netHelper.Write("StreamFiles:(Size)" + filesection.Body.Length);

                    fileName = MultipartRequestHelper.GetFileName(contentDisposition);

                    //获得文件扩展名

                    string fileNameEx = Path.GetExtension(fileName);

                    if (!string.IsNullOrEmpty(fileNameEx)) fileNameEx = fileNameEx.ToLower();

 

                    if (!new List<string> { ".xls", ".xlsx", ".doc", ".docx", ".pdf", ".png", ".jpg", ".jpeg", ".zip", ".rar" }.Contains(fileNameEx))

                    {

                        return new MsgDto<string> { msg = "附件文件格式有误" };

                    }

                    var time = DateTime.Now.ToString("yyyyMMddHHmmssfff");

                    fileName = time + "_" + itemindex + fileNameEx;

                    Log4netHelper.Write("StreamFiles:(fileNameEx)" + fileName);

                    var loadBufferBytes = 1024;//这个是每一次从Http请求的section中读出文件数据的大小,单位是Byte即字节,这里设置为1024的意思是,每次从Http请求的section数据流中读取出1024字节的数据到服务器内存中,然后写入下面targetFileStream的文件流中,可以根据服务器的内存大小调整这个值。这样就避免了一次加载所有上传文件的数据到服务器内存中,导致服务器崩溃。

 

                    using (var targetFileStream = System.IO.File.Create(targetDirectory + "\\" + fileName))

                    {

                        //section.Body是System.IO.Stream类型,表示的是Http请求中一个section的数据流,从该数据流中可以读出每一个section的全部数据,所以我们下面也可以不用section.Body.CopyToAsync方法,而是在一个循环中用section.Body.Read方法自己读出数据,再将数据写入到targetFileStream

                        await filesection.Body.CopyToAsync(targetFileStream, loadBufferBytes);

                    }

                    items.Add(fileName);

                    itemindex++;

                }

                filesection = await reader.ReadNextSectionAsync();//用于读取Http请求中的下一个section数据

            }

            var rebackurl = "";

            if (items.Any())

            {

                var topname = items.First().Split('_')?.First() ?? "";

                if (items.Count == 1)

                {

                    foreach (var fileitem in items)

                    {

                        var fileNameEx = fileitem.Split('.').Last();

                        if (File.Exists(targetDirectory + "\\" + fileitem))

                        {

                            File.Move(targetDirectory + "\\" + fileitem, targetDirectory + "\\" + filecanvsname + topname + "." + fileNameEx);

                            rebackurl = filecanvsname + topname + "." + fileNameEx;

                        }

                    }

                }

                else

                {

                    //多个文件合并压缩包    

                    var fileinfos = new List<FileInfo>();

                    foreach (var fileitem in items)

                    {

                        if (!string.IsNullOrEmpty(fileitem))

                        {

                            var filename = targetDirectory + "\\" + fileitem;

                            fileinfos.Add(new FileInfo(filename));

                        }

                    }

                    rebackurl = ZipHelper.ZipCompress(fileinfos, targetDirectory, filecanvsname + topname);

                }

            }

            return new MsgDto<string> { success = true, data = rebackurl, msg = "上传成功" };

        }

 

(2)相关调用方法:

创建DisableFormValueModelBindingAttribute属性方法:

用于上传大型文件,以防止表单数据被读入内存、防止模型绑定访问表单数据

 

(3)文件限制大小:

Startup相关ConfigureServices加上方法

 //设置接收文件长度的最大值。

services.Configure<FormOptions>(x =>

{

      x.ValueLengthLimit = int.MaxValue;

      x.MultipartBodyLengthLimit = int.MaxValue;

      x.MultipartHeadersLengthLimit = int.MaxValue;

});

(4)iis限制文件大小

发布后创建web.config设置允许最大传输的文件大小

 

 

 

 webapi接口调用方法:

 

标签:文件,fileNameEx,NetCore,section,var,new,上传
来源: https://www.cnblogs.com/wulala9/p/15319888.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有