在ASP.NET MVC中实现大文件异步上传(1)
2011-04-15 16:50
661 查看
绝大多数人认为在ASP.NET中上传大文件有以下这些解决方案:
◆不要这样做。你最好是在页面中嵌入一个Silverlight或Flash进程上传文件。
◆不要这样做。因为HTTP本身设计就不是为了上传大文件,重新思考你要的功能。
◆不要这样做。ASP.NET本身设计最大也就能处理2GB大小的文件。
◆购买商业产品,如SlickUpload,它使用了一个HttpModule实现了文件流分块。
◆使用开源产品,如NeatUpload,它使用了一个HttpModule实现了文件流分块。
最近我接到一个任务,需构建一个上传工具实现以下功能:
◆必须工作在HTTP协议
◆必须允许非常大的文件上传(会大于2GB)
◆必须允许断点续传
◆必须允许并行上传
因此前三个解决方案都不适应我的需求,其它解决方案对于我而言又太笨重了,因此我开始着手解决在ASP.NET MVC中的这个问题,如果有这方面的开发背景,你一定了解大部分问题最终都归结于对ASP.NET输入流和连锁请求过程的控制,网上的资料一般都是这样描述的,只要你的代码访问了HttpRequest的InputStream属性,在你访问流之前,ASP.NET就会缓存整个上传的文件,这就意味着当我向云服务上传文件时,我必须等待整个大文件抵达服务器,然后才能将其传输到预定目的地,这意味着需要两倍的时间。
首先,我们推荐你阅读一下Scott Hanselman的有关ASP.NET MVC文件上传文章,地址http://www.hanselman.com/blog/CommentView.aspx?guid=bc137b6b-d8d0-47d1-9795-f8814f7d1903,先对文件上传有一个大致的了解,但Scott Hanselman的方法是不能上传大文件的,根据Scott Hanselman的方法,你只需要修改一下web.config文件,确保ASP.NET允许最大支持2GB大小的文件上传,不要担心,这样设置并不会吃掉你的内存,因为凡是大于256KB的数据都被缓存到磁盘上去了。
这是一个简单的适合大多数应用的解决办法,但我的任务中不能借用这种方法,即使会将数据缓存到磁盘中,但这种类似于另存为的方法也会使用大量的内存。
那么在ASP.NET MVC中通过直接访问流,不触发任何缓存机制,上传大文件该如何实现呢?解决办法就是尽量远离ASP.NET,我们先来看一看UploadController,它有三个行为方法,一个是索引我们上传的文件,一个是前面讨论的缓存逻辑,另一个是基于实时流的方法。
虽然这里明显缺少一两个类,但基本的方法还是讲清楚了,看起来和缓存逻辑并没有太大的不同之处,我们仍然将流缓存到了磁盘,但具体处理方式却有些不同了,首先,没有与方法关联的属性,谓词和授权限制都被移除了,使用手动等值取代了,使用手工响应操作而不用ActionFilterAttribute声明的原因是这些属性涉及到了一些重要的ASP.NET管道代码,实际上在我的代码中,我还特意拦截了原生态的HttpWorkerRequest,因为它不能同时做两件事情。
◆不要这样做。你最好是在页面中嵌入一个Silverlight或Flash进程上传文件。
◆不要这样做。因为HTTP本身设计就不是为了上传大文件,重新思考你要的功能。
◆不要这样做。ASP.NET本身设计最大也就能处理2GB大小的文件。
◆购买商业产品,如SlickUpload,它使用了一个HttpModule实现了文件流分块。
◆使用开源产品,如NeatUpload,它使用了一个HttpModule实现了文件流分块。
最近我接到一个任务,需构建一个上传工具实现以下功能:
◆必须工作在HTTP协议
◆必须允许非常大的文件上传(会大于2GB)
◆必须允许断点续传
◆必须允许并行上传
因此前三个解决方案都不适应我的需求,其它解决方案对于我而言又太笨重了,因此我开始着手解决在ASP.NET MVC中的这个问题,如果有这方面的开发背景,你一定了解大部分问题最终都归结于对ASP.NET输入流和连锁请求过程的控制,网上的资料一般都是这样描述的,只要你的代码访问了HttpRequest的InputStream属性,在你访问流之前,ASP.NET就会缓存整个上传的文件,这就意味着当我向云服务上传文件时,我必须等待整个大文件抵达服务器,然后才能将其传输到预定目的地,这意味着需要两倍的时间。
首先,我们推荐你阅读一下Scott Hanselman的有关ASP.NET MVC文件上传文章,地址http://www.hanselman.com/blog/CommentView.aspx?guid=bc137b6b-d8d0-47d1-9795-f8814f7d1903,先对文件上传有一个大致的了解,但Scott Hanselman的方法是不能上传大文件的,根据Scott Hanselman的方法,你只需要修改一下web.config文件,确保ASP.NET允许最大支持2GB大小的文件上传,不要担心,这样设置并不会吃掉你的内存,因为凡是大于256KB的数据都被缓存到磁盘上去了。
﹤system.web﹥ ﹤httpruntime requestlengthdiskthreshold="256" maxrequestlength="2097151"﹥ ﹤/httpruntime﹥﹤/system.web﹥ |
那么在ASP.NET MVC中通过直接访问流,不触发任何缓存机制,上传大文件该如何实现呢?解决办法就是尽量远离ASP.NET,我们先来看一看UploadController,它有三个行为方法,一个是索引我们上传的文件,一个是前面讨论的缓存逻辑,另一个是基于实时流的方法。
public class UploadController : Controller { [AcceptVerbs(HttpVerbs.Get)] [Authorize] public ActionResult Index() { return View(); } [AcceptVerbs(HttpVerbs.Post)] public ActionResult BufferToDisk() { var path = Server.MapPath("~/Uploads"); foreach (string file in Request.Files) { var fileBase = Request.Files[file]; try { if (fileBase.ContentLength > 0) { fileBase.SaveAs(Path.Combine(path, fileBase.FileName)); } } catch (IOException) { } } return RedirectToAction("Index", "Upload"); } //[AcceptVerbs(HttpVerbs.Post)] //[Authorize] public void LiveStream() { var path = Server.MapPath("~/Uploads"); var context = ControllerContext.HttpContext; var provider = (IServiceProvider)context; var workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); //[AcceptVerbs(HttpVerbs.Post)] var verb = workerRequest.GetHttpVerbName(); if(!verb.Equals("POST")) { Response.StatusCode = (int)HttpStatusCode.NotFound; Response.SuppressContent = true; return; } //[Authorize] if(!context.User.Identity.IsAuthenticated) { Response.StatusCode = (int)HttpStatusCode.Unauthorized; Response.SuppressContent = true; return; } var encoding = context.Request.ContentEncoding; var processor = new UploadProcessor(workerRequest); processor.StreamToDisk(context, encoding, path); //return RedirectToAction("Index", "Upload"); Response.Redirect(Url.Action("Index", "Upload")); } } |
相关文章推荐
- ASP.NET MVC 使用Uploadify实现多文件异步无刷新上传
- (转)在ASP.NET MVC中实现大文件异步上传
- 在ASP.NET MVC中实现大文件异步上传
- 在ASP.NET MVC中实现大文件异步上传(2)
- 在ASP.NET MVC中实现大文件异步上传(2)
- 在ASP.NET MVC中实现大文件异步上传(2)
- ASP.NET MVC 网站开发总结(二)——一个或多个文件的异步或同步上传
- asp.net下实现支持文件分块多点异步上传的 Web Services
- asp.net mvc实现上传文件
- [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传
- asp.net下实现支持文件分块多点异步上传的 Web Services
- ASP.NET MVC 文件异步上传问题处理
- c#、asp.net 基于ajaxfileupload.js 实现文件异步上传
- Asp.net实现MVC处理文件的上传下载功能实例教程
- 用Html5与Asp.net MVC上传多个文件的实现代码
- ASP.NET MVC实现多文件上传
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
- 为ASP.NET MVC开发一些常用插件(二)—— 实现无刷新文件上传
- Asp.net实现MVC处理文件的上传下载功能实例教程
- 关于jQuery在Asp.Net Mvc 框架下Ajax文件上传的实现