对于asp.net,默认只允许上传2M文件,增加如下配置,一般可以自定义最大文件大小.
<httpRuntime executionTimeout="300" maxRequestLength="40960" useFullyQualifiedRedirectUrl="false"/>
我们在上传大文件时都遇到过这样或那样的问题。设置很大的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里分块读取数据,Chris Hynes为我们提供了这样的一个方案(用HttpModule),该方案除了允许你上传大文件外,还能实时显示上传进度。
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(Krystalware.HttpUploadManager)实现 ASP.NET大文件上传的代码:
(其中HttpUploadSpike.rar是 ASP.NET大文件上传开源版本[有一些小BUG,修改方法见下文]
SlickUpload-2.5.2.rar是 ASP.NET大文件上传最新的非开源版本)
使用Chris Hynes提供的代码进行大文件上传非常方便,但在使用过程中发现几个小问题,解决后给大家作个参考。
一、中途取消时CPU占用过高
上传的时候如果中途取消,w3wp进程占用CPU一直100%,经过跟踪发现
MultipartParser.cs中几处地方有问题:
1)ReadFile中处理Stream.Read的返回值
只处理出错返回-1的情况,没有处理到达流末尾返回0的情况
protected bool ReadFile(FilePart p)
{
// while (read != -1)
// 改为:
while (read > 0)
{
}
}
2)ReadLine中处理Stream.ReadByte的返回值
当到达流末尾ReadByte返回-1
ReadLine(Stream s)
{
int rcv = s.ReadByte();
if(rcv == -1)
break;
char current = (char)rcv;
}
二、中文文件名乱码
原来的代码在处理HTTP头的时候未考虑编码,我参考“天下“先生的代码修改ReadLine如下:
protected string ReadLine(Stream s)
{
byte[] tempValues = new byte[2048];
int i = 0;
while(i < 2048)
{
int rcv = s.ReadByte();
if(rcv == -1)
break;
byte current = (byte)rcv;
if(current != '/r' && current != '/n')
{
tempValues[i] = current;
i++;
}
else
{
if (current == '/r')
s.ReadByte();
break;
}
}
byte[] newValues = new byte[i];
Array.Copy(tempValues, newValues, (long)i);
return Encoding.Default.GetString(newValues);
}
这样保存的文件名就不是乱码了。
------------------------------------------------------------------------------------------------------------------------------
2/应该是超过4096K就报错,这是因为mechine.config中上传文件的最大默认值为4096K,在你的machine.config中加入以下代码:
<httpRuntime maxRequestLength="你想要的上传文件的最大值" />
machine.config文件在WINNT目录下的.NET Framework目录下:
如:C:/WINNT/Microsoft.NET/Framework/v1.0.3705/CONFIG