最近在做项目时,需要用到一个文件上传下载的组件,于是去网上搜集了一下这方面的资料,归纳如下:
1、http://blog.joycode.com/saucer/archive/2004/03/16/16225.aspx
我们在上传大文件时都遇到过这样或那样的问题。设置很大的maxRequestLength值并不能完全解决问题,因为ASP.NET会block直到把整个文件载入内存后,再加以处理。实际上,如果文件很大的话,我们经常会见到Internet Explorer显示 "The page cannot be displayed - Cannot find server or DNS Error",好像是怎么也catch不了这个错误。为什么?因为这是个client side错误,server side端的Application_Error是处理不到的,可以参考这个帖子研究一下产生这个错误的机理。
handling server error when upload file too large
解决的方法是利用隐含的HttpWorkerRequest,用它的GetPreloadedEntityBody 和 ReadEntityBody方法从IIS为ASP.NET建立的pipe里分块读取数据
IServiceProvider provider = (IServiceProvider) HttpContext.Current;
HttpWorkerRequest wr = (HttpWorkerRequest) provider.GetService(typeof(HttpWorkerRequest));
byte[] bs = wr.GetPreloadedEntityBody();
....
if (!wr.IsEntireEntityBodyIsPreloaded())
{
int n = 1024;
byte[] bs2 = new byte[n];
while (wr.ReadEntityBody(bs2,n) >0)
{
.....
}
}
Chris Hynes为我们提供了这样的一个方案(用HttpModule),该方案除了允许你上传大文件外,还能实时显示上传进度:
这里有他讲座的PPT文件:
Uploading with ASP.NET (part 1)
Uploading with ASP.NET (part 2)
2、http://www.cnblogs.com/WuCountry/archive/2006/10/16/306725.html
ASP.net下大文件上传的解决方案及WebbUpload组件源码
WebbUpload上传组件
特性简介
可上传上小于1G的文件,可以配置Web.config文件来设定上传文件的大小。
完全基于.NET开发,无需任何客户端配置。
提供同步的上传进度条,显示实时上传进度信息。
不破坏页面逻辑,提供类似ASP.NET内置上传组件的使用方法。
不受 Server.ScriptTimeout(请求的超时设置) 影响,可配置服务器处理时间。
开发测试环境
操作系统:Windows XP Professional(en)
开发工具:Microsoft Visual Studio.NET 2003
WEB服务器:IIS 5.0 & .NET Framework 1.1
浏览器:Internet Explorer 6.0/
2005-12-28更新说明:
1、修改了多文件上传时文件列表项为空时的错误。
2、更新了进度条的文件名显示方法,只保留文件名,删除了路径。
下载 http://www.cnblogs.com/Files/WuCountry/WebbUploadSample.rar
关于WebbUpload上传组件的开发请查看相关链接:http://computer.mblogger.cn/wucountry/posts/48947.aspx
2006-01-25 第二次更新:
下载:http://www.cnblogs.com/Files/WuCountry/WebbUploadSample.zip
说明:
1、修改了一下上传进度条。
2、添加了几个属性,并修改了一个类名,原来的WebbUploadHandler改为WebbUploadStatusHandler。
3、可以不破坏HttpinpuFile上传,只用在调用时调用方法:EnableWebbUpload(false);就可以使用原来的上传方法。默认是使用WebbUpload.
4、本次下载文件里有演示的完整源代码。
相信本次修改会会使该组件越来越稳定,而且在我的实际项目里一直在使用。
2006-02-17
公开全部源代码。
昨天同事给了我一个工具,可以把DLL文件逆向为工程项目。所以这个上传组件也就没有必须在保护源代码了。
本来考虑到ASPNetUpload的商业行为,还准备暂时不公开这个组件的源代码,但这已经没有意义了。
Webb.WAVE.Controls.WebbUpload控件全部源代码:
http://www.cnblogs.com/Files/WuCountry/WebbUpload.zip
结合上面的演示实例,应该是一个很好的学习项目。
3、http://soft.yesky.com/79/2596079.shtml
ASP.NET 应用中大文件上传研究
现在国内使用的大文件上传的组件发现用的比较多的有两个控件AspnetUpload 2.0和Lion.Web.UpLoadModule,两个控件的方法是:利用隐含的HttpWorkerRequest,用它的GetPreloadedEntityBody 和 ReadEntityBody方法从IIS为ASP.NET建立的pipe里分块读取数据。Chris Hynes为我们提供了这样的一个方案(用HttpModule),该方案除了允许你上传大文件外,还能实时显示上传进度。
Lion.Web.UpLoadModule和AspnetUpload 两个.NET组件都是利用的这个方案。
当上传单文件时,两个软件的方法是一样的,继承HttpModule
HttpApplication application1 = sender as HttpApplication; HttpWorkerRequest request1 = (HttpWorkerRequest) ((IServiceProvider) HttpContext.Current).GetService(typeof(HttpWorkerRequest)); try { if (application1.Context.Request.ContentType.IndexOf("multipart/form-data") <= -1) { return; } //Check The HasEntityBody if (!request1.HasEntityBody()) { return; } int num1 = 0; TimeSpan span1 = DateTime.Now.Subtract(this.beginTime); string text1 = application1.Context.Request.ContentType.ToLower(); byte[] buffer1 = Encoding.ASCII.GetBytes(("/r/n--" + text1.Substring(text1.IndexOf("boundary=") + 9)).ToCharArray()); int num2 = Convert.ToInt32(request1.GetKnownRequestHeader(11)); Progress progress1 = new Progress(); application1.Context.Items.Add("FileList", new Hashtable()); byte[] buffer2 = request1.GetPreloadedEntityBody(); num1 += buffer2.Length; string text2 = this.AnalysePreloadedEntityBody(buffer2, "UploadGUID"); if (text2 != string.Empty) { application1.Context.Items.Add("LionSky_UpLoadModule_UploadGUID", text2); } bool flag1 = true; if ((num2 > this.UpLoadFileLength()) && ((0 > span1.TotalHours) || (span1.TotalHours > 3))) { flag1 = false; } if ((0 > span1.TotalHours) || (span1.TotalHours > 3)) { flag1 = false; } string text3 = this.AnalysePreloadedEntityBody(buffer2, "UploadFolder"); ArrayList list1 = new ArrayList(); RequestStream stream1 = new RequestStream(buffer2, buffer1, null, RequestStream.FileStatus.Close, RequestStream.ReadStatus.NoRead, text3, flag1, application1.Context, string.Empty); list1.AddRange(stream1.ReadBody); if (text2 != string.Empty) { progress1.FileLength = num2; progress1.ReceivedLength = num1; progress1.FileName = stream1.OriginalFileName; progress1.FileCount = ((Hashtable) application1.Context.Items["FileList"]).Count; application1.Application["_UploadGUID_" + text2] = progress1; } if (!request1.IsEntireEntityBodyIsPreloaded()) { byte[] buffer4; ArrayList list2; int num3 = 204800; byte[] buffer3 = new byte[num3]; while ((num2 - num1) >= num3) { if (!application1.Context.Response.IsClientConnected) { this.ClearApplication(application1); } num3 = request1.ReadEntityBody(buffer3, buffer3.Length); num1 += num3; list2 = stream1.ContentBody; if (list2.Count > 0) { buffer4 = new byte[list2.Count + buffer3.Length]; list2.CopyTo(buffer4, 0); buffer3.CopyTo(buffer4, list2.Count); stream1 = new RequestStream(buffer4, buffer1, stream1.FileStream, stream1.FStatus, stream1.RStatus, text3, flag1, application1.Context, stream1.OriginalFileName); } else { stream1 = new RequestStream(buffer3, buffer1, stream1.FileStream, stream1.FStatus, stream1.RStatus, text3, flag1, application1.Context, stream1.OriginalFileName); } list1.AddRange(stream1.ReadBody); if (text2 != string.Empty) { progress1.ReceivedLength = num1; progress1.FileName = stream1.OriginalFileName; progress1.FileCount = ((Hashtable) application1.Context.Items["FileList"]).Count; application1.Application["_UploadGUID_" + text2] = progress1; } } buffer3 = new byte[num2 - num1]; if (!application1.Context.Response.IsClientConnected && (stream1.FStatus == RequestStream.FileStatus.Open)) { this.ClearApplication(application1); } num3 = request1.ReadEntityBody(buffer3, buffer3.Length); list2 = stream1.ContentBody; if (list2.Count > 0) { buffer4 = new byte[list2.Count + buffer3.Length]; list2.CopyTo(buffer4, 0); buffer3.CopyTo(buffer4, list2.Count); stream1 = new RequestStream(buffer4, buffer1, stream1.FileStream, stream1.FStatus, stream1.RStatus, text3, flag1, application1.Context, stream1.OriginalFileName); } else { stream1 = new RequestStream(buffer3, buffer1, stream1.FileStream, stream1.FStatus, stream1.RStatus, text3, flag1, application1.Context, stream1.OriginalFileName); } list1.AddRange(stream1.ReadBody); if (text2 != string.Empty) { progress1.ReceivedLength = num1 + buffer3.Length; progress1.FileName = stream1.OriginalFileName; progress1.FileCount = ((Hashtable) application1.Context.Items["FileList"]).Count; if (flag1) { progress1.UploadStatus = Progress.UploadStatusEnum.Uploaded; } else { application1.Application.Remove("_UploadGUID_" + text2); } } } byte[] buffer5 = new byte[list1.Count]; list1.CopyTo(buffer5); this.PopulateRequestData(request1, buffer5); } catch (Exception exception1) { this.ClearApplication(application1); throw exception1; } |
4、 http://www.cnblogs.com/overred/archive/2007/04/12/710894.html
引用:
包含2个自定义控件:
*用户可以通过INPUTFILE选择一个要上传的文件。
*ProgressBar可以用进度条方式或弹出窗方式显示上传进度。当JavaScript可用时ProgressBar是用类似AJAX的无刷新方式展现,但也允许JavaScript不可用的用户见到上传进度
演示地址:http://www.brettle.com/Demo.aspx
下载地址:http://www.brettle.com/neatupload#Download
以上几个上传下载组件
WebbUpload
AspnetUpload
Lion.Web.UpLoadModule
NeatUpload
大都试用了一下,感觉提供源代码的WebbUpload组件不错,测试了一下,还不错,最主要是提供了源代码,可以二次开发。