最新要闻
- 悦达起亚大地震!管理层轮休1年 公司资不抵债|世界实时
- MAXHUB双发x86兆芯、Arm飞腾国产CPU电脑!国产化近95%
- 单卡30秒跑出虚拟3D仙女老婆!毛孔细节清晰
- 女子退货8600元鞋被拒收:退回后鞋出现磨损
- 杭州现不定价咖啡店 营业首日卖400杯亏3500元!创始人回应|微头条
- 每日速看!gai周延参加的综艺有哪些_周延gai百度百科
- 特斯拉晒美国电价/油价:每天开电车50公里 一月省700块 天天观热点
- 盗版大神正式出手破解《生化危机4重制版》:Denuvo加密沦陷|当前快报
- 每日焦点!《生化危机4:重置版》碍事梨演员再发cos照:里昂救救我!
- 焦点热讯:首发2亿单镜变焦相机!真我11 Pro+图赏
- Win10杀软大PK:Defender拿了个倒数第一_焦点速看
- 泉州市丰泽区东海东宝工业区改造征迁工作指挥部正式揭牌成立
- 无锡阳山桃花源景区可以摘桃子吗_天天速看料
- 环球焦点!因不富裕 《王国之泪》粉丝攒钱6年才买到Switch
- 杀疯了!理想汽车公布2023年第一季度财报:营收、交付等多项数据历史最好
- 男子暴雨天救助流浪猫 专家确认:国家二级保护动物
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
ASP.NET Core MVC 从入门到精通之文件上传 世界快资讯
随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,或其他想从事ASP.NET Core MVC 系统开发的人员。 经过前几篇文章的讲解,初步了解ASP.NET Core MVC项目创建,启动运行,以及命名约定,创建控制器,视图,模型,接收参数,传递数据ViewData,ViewBag,路由,页面布局,wwwroot和客户端库,Razor语法,EnityFrameworkCore与数据库,HttpContext,Request,Response,Session,序列化等内容,今天继续讲解ASP.NET Core MVC 中文件上传等相关内容,仅供学习分享使用。
概述
在实际应用开发中,文件上传是非常常见的功能,文件上传主要分为单文件上传,多文件上传,文件与其他内容混合上传,大文件上传几种情况,本文会分别讲解。
IFormFile
在ASP.NET Core MVC项目中,IFormFile表示使用 HttpRequest 发送的文件,可以用于文件流的接收。将整个文件读入IFormFile。IFormFile
是用于处理或保存文件的文件的 C# 表示形式。
【资料图】
文件上传使用的磁盘和内存取决于并发文件上传的数量和大小。 如果应用尝试缓冲过多上传,站点就会在内存或磁盘空间不足时崩溃。 如果文件上传的大小或频率会消耗应用资源,请使用流式传输。
IFormFile的属性和方法如下:
对于小文件的上传,一般采用IFormFile;大文件上传,采用流式上传,已实现可靠稳定传输。
IWebHostEnvironment 站点环境信息,用于获取站点根目录等内容。
单个文件上传
单文件上传功能主要分为两部分:文件上传视图和后台处理方法。
1. 文件上传视图
首先创建视图,用于单个文件上传。关于视图有两点说明,如下所示:
- 文件上传通过form表单,采用post方式,加密类型为multipart/form-data
- 文件上传采用input控件,类型为file。
视图代码如下所示:
1
2. 后台处理方法
form提交后台处理方法OneFileUpload,关于处理方法有几点说明,如下所示:
- 方法中的参数IFormFile file用于接收客户端上传的文件,其他file和视图中上传控件的name一一对应。如果错误,则无法上传。
- _webHostEnvironment 为控制器通过接口注入的IWebHostEnvironment类型的获取站点信息接口,主要用于获取站点根目录。
- 调用IFormFile的CopyTo方法进行保存,此方法接收Stream类型的参数。
上传处理代码,如下所示:
1 ///2 /// 单文件上传 3 /// 4 ///5 public IActionResult OneFileUpload(IFormFile file) 6 { 7 var path = Path.Combine(_webHostEnvironment.ContentRootPath, "uploads", string.Format("{0}_{1}", DateTime.Now.Ticks, file.FileName)); 8 using (FileStream fs = new FileStream(path, FileMode.Create)) 9 {10 file.CopyTo(fs);11 }12 return Ok("上传成功");13 }
多文件上传
多文件上传表示一次可以上传多个文件。。上传功能主要分为两部分:文件上传视图和后台处理方法。
1. 多文件上传视图
input控件在类型为file时表示文件上传,默认是单个文件上传,通过设置multiple属性,可实现多文件上传。视图代码如下所示:
1
2. 多文件后台处理方法
多个文件上传,参数为IFormFile数组类型,可以接受上传文件列表,然后循环获取并进行保存即可。如下所示:
1 ///2 /// 多文件上传 3 /// 4 ///5 public IActionResult MoreFileUpload(IFormFile[] files) 6 { 7 foreach (var file in files) 8 { 9 var path = Path.Combine(_webHostEnvironment.ContentRootPath, "uploads", string.Format("{0}_{1}", DateTime.Now.Ticks, file.FileName));10 using (FileStream fs = new FileStream(path, FileMode.Create))11 {12 file.CopyTo(fs);13 }14 }15 16 return Ok("上传成功");17 }
文件文本混合上传
在实际应用中,文件上传只是一部分,还需要搭配其他的文本说明,如录入产品信息,并上传附件等。
1. 创建模型
在Product中,包含两个属性,一个字符串类型的Name,用于绑定名称,一个IFormFile类型的File,用于上传文件。如下所示:
1 namespace DemoCoreMVC.Models2 {3 public class Product4 {5 public string Name { get; set; }6 7 public IFormFile File { get; set; }8 }9 }
2. 视图绑定模型
在视图最顶部,为视图指定模型,如下所示:
1 @model DemoCoreMVC.Models.Product
3. 混合文本文件上传视图
在form表单中,除了文件上传控件,还有一个文件框,用于输入名称。其中控件name和模型相对应。如下所示:
1
4. 后台处理方法
文件文本混合上传,参数为模型Product,通过属性匹配接收参数,然后获取属性File对应的内存流进行保存即可。如下所示:
1 ///2 /// 文件内容混合上传 3 /// 4 ///5 public IActionResult FileWithContentUpload(Product product) 6 { 7 var file = product.File; 8 var path = Path.Combine(_webHostEnvironment.ContentRootPath, "uploads", string.Format("{0}_{1}", DateTime.Now.Ticks, file.FileName)); 9 using (FileStream fs = new FileStream(path, FileMode.Create))10 {11 file.CopyTo(fs);12 }13 return Ok($"{product.Name} 上传成功");14 }
大文件上传
首先如何界定大文件/小文件,并没有统一的标准。根据官网相关参数说明:
- 默认情况下,HttpRequest.Form不会缓冲整个请求正文 (BufferBody) ,但会缓冲包含的任何多部分表单文件。
- MultipartBodyLengthLimit是缓冲表单文件的最大大小,默认值为 128MB。
- MemoryBufferThreshold指示在转换为磁盘上的缓冲区文件之前,内存中的文件缓冲量,默认为 64KB。
MemoryBufferThreshold
充当小型和大型文件之间的边界,这些文件根据应用资源和方案而引发或降低。
大文件上传采用流式传输,可降低上传文件时对内存或磁盘空间的需求。
1. 创建视图
大文件和小文件上传在视图上并无差别,只是后台处理方法不同,如下所示:
1
2. 后台处理方法
首先创建大文件上传帮助类MultipartRequestHelper,如下所示:
1 using System; 2 using System.IO; 3 using Microsoft.Net.Http.Headers; 4 namespace DemoCoreMVC 5 { 6 public static class MultipartRequestHelper 7 { 8 // Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq" 9 public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)10 {11 var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;12 13 if (string.IsNullOrWhiteSpace(boundary))14 {15 throw new InvalidDataException("Missing content-type boundary.");16 }17 18 if (boundary.Length > lengthLimit)19 {20 throw new InvalidDataException(21 $"Multipart boundary length limit {lengthLimit} exceeded.");22 }23 24 return boundary;25 }26 27 public static bool IsMultipartContentType(string contentType)28 {29 return !string.IsNullOrEmpty(contentType)30 && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;31 }32 33 public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)34 {35 // Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"36 return contentDisposition != null37 && contentDisposition.DispositionType.Equals("form-data")38 && (!string.IsNullOrEmpty(contentDisposition.FileName.Value)39 || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));40 }41 42 // 如果一个section的Header是: Content-Disposition: form-data; name="myfile1"; filename="F:\Misc 002.jpg"43 // 那么本方法返回: Misc 002.jpg44 public static string GetFileName(ContentDispositionHeaderValue contentDisposition)45 {46 return Path.GetFileName(contentDisposition.FileName.Value);47 }48 49 }50 }
处理方法BigFileUploadAsync,关于Action说明,如下所示:
Action中要进行DisableRequestSizeLimit特性说明,否则会有大小限制【InvalidDataException: Multipart body length limit 16384 exceeded】。
在该操作中,使用MultipartReader
读取窗体的内容,它会读取每个单独的MultipartSection
,从而根据需要处理文件或存储内容。 读取多部分节后,该操作会执行自己的模型绑定。
1 ///2 /// 大文件上传 3 /// 4 ///5 [DisableRequestSizeLimit] 6 public async Task BigFileUploadAsync() 7 { 8 var contentType = Request.ContentType; 9 if (!MultipartRequestHelper.IsMultipartContentType(contentType))10 {11 ModelState.AddModelError("File",12 $"上传文件类型不对.");13 return BadRequest(ModelState);14 }15 var path = Path.Combine(_webHostEnvironment.ContentRootPath, "uploads");16 17 var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);18 19 var reader = new MultipartReader(boundary, HttpContext.Request.Body);20 21 var section = await reader.ReadNextSectionAsync();22 23 while (section != null)24 {25 var hasContentDispositionHeader =26 ContentDispositionHeaderValue.TryParse(27 section.ContentDisposition, out var contentDisposition);28 29 if (hasContentDispositionHeader)30 {31 if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition))32 {33 ModelState.AddModelError("File",34 $"The request couldn"t be processed (Error 2).");35 36 return BadRequest(ModelState);37 }38 else39 {40 var fileName = MultipartRequestHelper.GetFileName(contentDisposition);41 var loadBufferBytes = 1024;//这个是每一次从Http请求的section中读出文件数据的大小,单位是Byte即字节,这里设置为1024的意思是,每次从Http请求的section数据流中读取出1024字节的数据到服务器内存中,然后写入下面targetFileStream的文件流中,可以根据服务器的内存大小调整这个值。这样就避免了一次加载所有上传文件的数据到服务器内存中,导致服务器崩溃。42 43 using (var targetFileStream = new FileStream(path + "\\" + string.Format("{0}_{1}", DateTime.Now.Ticks, fileName), FileMode.Create, FileAccess.ReadWrite))44 {45 using (section.Body)46 {47 //section.Body是System.IO.Stream类型,表示的是Http请求中一个section的数据流,从该数据流中可以读出每一个section的全部数据,所以我们下面也可以不用section.Body.CopyToAsync方法,而是在一个循环中用section.Body.Read方法自己读出数据(如果section.Body.Read方法返回0,表示数据流已经到末尾,数据已经全部都读取完了),再将数据写入到targetFileStream48 await section.Body.CopyToAsync(targetFileStream, loadBufferBytes);49 }50 }51 }52 }53 section = await reader.ReadNextSectionAsync();54 }55 return Ok("上传成功");56 }
注意:在文件上传功能中,上传后的文件一般都要进行重命名的,否则如何客户端上传相同名称的文件,则可能会被覆盖。在本例中,在原文件前面加上了时间戳,以减少重复的概率。
文件上传校验
在实际开发中,为了避免客户端上传不满足条件的文件,一般都会进行校验。
- 文件扩展名验证:应在允许的扩展名列表中查找上传的文件的扩展名。
- 文件签名验证:文件的签名由文件开头部分中的前几个字节确定。 可以使用这些字节指示扩展名是否与文件内容匹配。 示例应用检查一些常见文件类型的文件签名。
- 文件名安全:切勿使用客户端提供的文件名来将文件保存到物理存储。
- 文件大小验证:限制上传的文件的大小。
文件上传安全
为避免文件上传功能造成攻击可能性,常规安全措施如下:
- 将文件上传到专用文件上传区域,最好是非系统驱动器。 使用专用位置便于对上传的文件实施安全限制。 禁用对文件上传位置的执行权限。
- 请勿将上传的文件保存在与应用相同的目录树中。
- 使用应用确定的安全的文件名。 请勿使用用户提供的文件名或上传的文件的不受信任的文件名。† 当显示不受信任的文件名时 HTML 会对它进行编码。 例如,记录文件名或在 UI 中显示(Razor 自动对输出进行 HTML 编码)。
- 按照应用的设计规范,仅允许已批准的文件扩展名。
- 验证是否对服务器执行客户端检查。† 客户端检查易于规避。
- 检查已上传文件的大小。 设置一个大小上限以防止上传大型文件。
- 文件不应该被具有相同名称的上传文件覆盖时,先在数据库或物理存储上检查文件名,然后再上传文件。
- 先对上传的内容运行病毒/恶意软件扫描程序,然后再存储文件。
参考文章
本篇文章主要参考内容如下:
1. 官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/mvc/models/file-uploads?view=aspnetcore-6.0
以上就是ASP.NET Core MVC从入门到精通之文件上传的全部内容。
关键词:
ASP.NET Core MVC 从入门到精通之文件上传 世界快资讯
债市日报:5月10日_世界观焦点
美国债务上限谈判无进展 拜登可能取消G7行程 热文
悦达起亚大地震!管理层轮休1年 公司资不抵债|世界实时
MAXHUB双发x86兆芯、Arm飞腾国产CPU电脑!国产化近95%
单卡30秒跑出虚拟3D仙女老婆!毛孔细节清晰
女子退货8600元鞋被拒收:退回后鞋出现磨损
杭州现不定价咖啡店 营业首日卖400杯亏3500元!创始人回应|微头条
每日聚焦:Python中的交互库-os库
IPS 和 IDS_观热点
每日速看!gai周延参加的综艺有哪些_周延gai百度百科
特斯拉晒美国电价/油价:每天开电车50公里 一月省700块 天天观热点
盗版大神正式出手破解《生化危机4重制版》:Denuvo加密沦陷|当前快报
每日焦点!《生化危机4:重置版》碍事梨演员再发cos照:里昂救救我!
焦点热讯:首发2亿单镜变焦相机!真我11 Pro+图赏
Win10杀软大PK:Defender拿了个倒数第一_焦点速看
泉州市丰泽区东海东宝工业区改造征迁工作指挥部正式揭牌成立
如何衡量软件测试的绩效 环球速讯
无锡阳山桃花源景区可以摘桃子吗_天天速看料
环球焦点!因不富裕 《王国之泪》粉丝攒钱6年才买到Switch
杀疯了!理想汽车公布2023年第一季度财报:营收、交付等多项数据历史最好
男子暴雨天救助流浪猫 专家确认:国家二级保护动物
四月厂商销量榜:国产车强势爆发 前五占三席
散片便宜300元!但还是劝你买盒装CPU|世界动态
热资讯!华能水电:拟收购华能四川能源开发公司100%股权
AI别来搅局,chatGPT的世界不懂低代码 焦点要闻
观察:理想汽车:预计第二季度车辆交付量7.6万至8.1万辆
滚动:1999元起 真我11 Pro+发布:同价位中的2亿像素王
热点!432核心 25个人开发!欧洲自研CPU飞入太空
淘宝天猫历史最大投入618:今年推出直降专场 不用费劲凑单领券 焦点速递
环球观察:爸爸因无人回应退家族群 女儿发声:反而变热闹了
天玑9000性能满载!vivo Pad2评测:操控如PC般行云流水_今日聚焦
环球热消息:4月销量仅6658台!不降价的蔚来,终于把自己玩懵了?
[系统性能优化实践]JVM进阶实战之监控工具(Prometheus) 焦点速递
STM32【HAL库】使用外部SRAM程序
世界新资讯:如何通过appuploader把ipa文件上传到App Store教程步骤
【高端访谈】碳交易市场将如何影响化工行业?——专访全国化工节能(减排)中心秘书长张华
甘肃凉州:让非遗民俗文化“活起来”|观焦点
年度最火的KEEP动感单车免费得:连续88天打卡全额返 焦点速看
实时:可灭电火、油火 北大青鸟车载灭火器620ml 12.92元
真我史上最大底 真我11 Pro+搭载行业最高2亿像素传感器:挑战最强 每日热门
环球快资讯丨特斯拉要疯?向所有用户开放超充 车主拍手友商跺脚
首发2099元!九号电动V30C发布:50km续航、车架终身质保 当前热点
微软修复 Win10 / Win11 上 BlackLotus UEFI 漏洞
【天天报资讯】java读取文件——以自动贩卖机为例
天天热门:最佳软件测试基础入门教程1简介
环球视点!自建CA和公共CA有什么不同?
基于华为云图引擎GES,使用Cypher子查询进行图探索
每日消息!Vue2组件间通讯
每日快讯!【新华500】新华500指数(989001)10日收跌0.65%
当前热讯:成功展商要点——2023第十二届北京国际汽车制造业博览会
环球即时:传音Tecno Camon 20系列发布:五边形镜组极具辨识度
当前资讯!《斗罗大陆双神战双神》首个场景秀公开:虚幻5打造 画面逼真
这就很尴尬 男子高速电话指导女友开车 结果自己撞了
世界看点:4699元起 九号智能电动车小Q发布:新国标、能跑95km
一图看懂联发科旗舰新U天玑9200+:CPU/GPU性能提升10%、功耗更低了
环球看点!男童喉咙长菜花样肿块确诊感染HPV
今日看点:89.关于类的定义抽象数据类型
全球观速讯丨Mac系统,Qt工程转xcode工程,打包pkg
大幅提升前端工作效率!Numeral.js数值格式化库来了!
无需代码绘制人工神经网络ANN模型结构图的方法
2023年梅花金银兔纪念币价格(2023年05月10日)_世界快资讯
仅7999元!Redmi MAX 90英寸巨屏电视开售:百级分区、144Hz高刷 即时焦点
每日热议!亏电百公里油耗3.9升 比亚迪驱逐舰07申报:凯美瑞、雅阁瑟瑟发抖
保时捷718上新款 157.8万元起!真心无法抗拒 全球简讯
环球快看点丨悦达起亚被曝管理岗轮休 一休就一年!官方回应
中国电信在科技创新中加速释放消费活力 每日聚焦
每日播报!利用Appuploader上架IPA步骤
环球热文:代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。第一章 数组part01
黄道十二宫是什么意思?黄道十二宫是哪个文明首先提出的?
每日看点!98年浙大女学霸曾被视为格力接班人 孟羽童称靠别人永远不如靠自己
金锣玉米热狗香肠20袋到手19.9元:新鲜美味 当前短讯
热讯:为什么这届年轻人基本不走亲戚了?互联网“断亲”情况加剧:专家释疑
【环球新视野】西渝高铁最新进展!200余户已签协议
双商最高的四大星座是什么?十二星座的月份表
神话Eric的妻子是谁?神话Eric个人介绍
2011年快乐女声有哪些评委?2011届快女排名前十名
消失日晖打一字是什么?猜字谜游戏题目及答案
台电平板怎么刷机?台电平板android版如何获取root?
会声会影x4激活步骤是什么?会声会影x4激活代码
华硕f83v笔记本电池充电时橙色充电灯不停闪烁怎么解决?华硕f83v笔记本参数
三星笔记本r467怎么进bios设置u盘启动?三星笔记本r467参数
Vue 前端开发团队风格指南(史上最全)
Linux ARM架构_安装JDK8-银河麒麟V10 Kylin Linux-焦点速递
PSP上哪个火影的游戏最好玩?PSP经典游戏有哪些?
商家广告鼓励偷男友钱喝奶茶被罚 热消息
环球通讯!苹果推出iPad版Final Cut Pro与Logic pro:1个月免费试用
国人秒懂内涵 如何辨别在美国的中国人:看车牌 环球今头条
吸、扫、拖三合一!米家免洗扫拖机器人2正式开售:1999元
深圳一男子举牌相亲 月薪6千要求女方1万2:被路人质疑后神回应 世界热门
史诗级尴尬!马斯克驾驶Cybertruck结果趴窝:在农田里陷车
2023年社保缴费基数怎么调整?什么时候重新申报?_环球新资讯
环球新资讯:2分钟快速上手流水线的创建与运行
当前视讯!接单日记(三)文本处理之词云生成
今日热门!台式电脑有线网络怎么连接_有线网络怎么连接
华为将发布双旗舰笔记本 MateBook新品颜值、性能将迎全面升级
世界热点!任天堂Switch卖不动了?销量下降22% 还要再苟一年
首发9999元 小米电视ES Pro 90寸开售:1000nits高亮度
今日观点!希思黎京东官方自营旗舰店开业 打造全新高端奢护体验
环球今日报丨支持双枪快充!比亚迪赵长江:腾势N7制动距离“遥遥领先”