积极答复者
上传大文件问题

问题
-
在网上找到一个上传大文件的方法,有些不明白的地方,请大家指教:
public void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
HttpWorkerRequest workRequest = GetWorkerRequest(application.Context);if (workRequest != null)
{
HttpRequest request = application.Request;
byte[] tempBuffer;//tempBuffer为何总是为null?
tempBuffer = workRequest.GetPreloadedEntityBody();if (IsUploadRequest(request))
{
Encoding encode = request.ContentEncoding;
int bytesRead = 0;
int read = 0;
int count = 8192;
byte[] buffer;
//为何当上传的文件很大的时候(我用了几百M、1.+G、3.+G的做测试,当用3.+G做测试时)length为负
long length = long.Parse(workRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
tempBuffer = tempBuffer == null ? new byte[count] : tempBuffer;
buffer = new byte[length];
count = tempBuffer.Length;bytesRead = tempBuffer.Length;
while (workRequest.IsClientConnected() && !workRequest.IsEntireEntityBodyIsPreloaded() && bytesRead < length)
{
if (bytesRead + count > length)
{
count = (int)(length - bytesRead);
tempBuffer = new byte[count];
}read = workRequest.ReadEntityBody(tempBuffer, count);
Buffer.BlockCopy(tempBuffer, 0, buffer, bytesRead, read);
bytesRead += read;
}if (workRequest.IsClientConnected() && !workRequest.IsEntireEntityBodyIsPreloaded())
{
// 传入已上传完的数据
//
InjectTextParts(workRequest, buffer);
}
}
}
}public HttpWorkerRequest GetWorkerRequest(HttpContext context)
{
IServiceProvider provider = (IServiceProvider)HttpContext.Current;
return (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
}/// <summary>
/// 是否为附件上传
/// 判断的根据是ContentType中有无multipart/form-data
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public bool IsUploadRequest(HttpRequest request)
{
string s1 = request.ContentType, s2 = "multipart/form-data";
return (string.Compare(s1, 0, s2, 0, s2.Length, true, CultureInfo.InvariantCulture) == 0);
}/// <summary>
/// 传入已上传完的数据
/// </summary>
/// <param name="request"></param>
/// <param name="textParts"></param>
public void InjectTextParts(HttpWorkerRequest request, byte[] textParts)
{
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;Type type = request.GetType();
while ((type != null) && (type.FullName != "System.Web.Hosting.ISAPIWorkerRequest"))
{
type = type.BaseType;
}if (type != null)
{
type.GetField("_contentAvailLength", bindingFlags).SetValue(request, textParts.Length);
type.GetField("_contentTotalLength", bindingFlags).SetValue(request, textParts.Length);
type.GetField("_preloadedContent", bindingFlags).SetValue(request, textParts);
type.GetField("_preloadedContentRead", bindingFlags).SetValue(request, true);
}
}主要有以下三个问题:
1、tempBuffer = workRequest.GetPreloadedEntityBody();----tempBuffer为何总是为null?
2、long length = long.Parse(workRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));为何当上传的文件很大的时候(我用了几百M、1.+G、3.+G的做测试,当用3.+G做测试时)length为负
3、这样上传能上传多大的文件,我只上传了几十M就上传不了了,长度太大关于第一个问题,网上有人说要用IIS,不用vs自带的服务器,我IIS7还是不行
希望大家不吝赐教
答案
-
Please try the following coding:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpRequest request = HttpContext.Current.Request;
if (request.ContentType.Contains("multipart/form-data") && request.ContentLength > 4194304)//4096000 is maxRequestLength
{
HttpApplication app = sender as HttpApplication;
HttpContext context = app.Context;
//HttpWorkerRequest workerRequest = (HttpWorkerRequest)(context.GetType().GetProperty("WorkerRequest", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(context, null));
IServiceProvider provider = (IServiceProvider)HttpContext.Current;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
if (workerRequest.HasEntityBody())
{
//int contentlen = Convert.ToInt32(wr.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
//buffer = wr.GetPreloadedEntityBody();
//int received = buffer.Length;
//int totalrecv = received;
// get the total body length
int requestLength = workerRequest.GetTotalEntityBodyLength();
// Get the initial bytes loaded
int initialBytes = 0;
if (workerRequest.GetPreloadedEntityBody() != null)
initialBytes = workerRequest.GetPreloadedEntityBody().Length;
if (!workerRequest.IsEntireEntityBodyIsPreloaded())
{
byte[] buffer = new byte[52000];
// Set the received bytes to initial bytes before start reading
int receivedBytes = initialBytes;
while (requestLength - receivedBytes >= initialBytes)
{
// Read another set of bytes
initialBytes = workerRequest.ReadEntityBody(buffer, buffer.Length);
// Update the received bytes
receivedBytes += initialBytes;
}
initialBytes = workerRequest.ReadEntityBody(buffer, requestLength - receivedBytes);
}
}
context.Response.Redirect("../UploadError.aspx");//Redirect to custom error page.
}
}- 已标记为答案 Alan.Deng 2010年4月1日 2:48
全部回复
-
Please try the following coding:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpRequest request = HttpContext.Current.Request;
if (request.ContentType.Contains("multipart/form-data") && request.ContentLength > 4194304)//4096000 is maxRequestLength
{
HttpApplication app = sender as HttpApplication;
HttpContext context = app.Context;
//HttpWorkerRequest workerRequest = (HttpWorkerRequest)(context.GetType().GetProperty("WorkerRequest", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(context, null));
IServiceProvider provider = (IServiceProvider)HttpContext.Current;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
if (workerRequest.HasEntityBody())
{
//int contentlen = Convert.ToInt32(wr.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
//buffer = wr.GetPreloadedEntityBody();
//int received = buffer.Length;
//int totalrecv = received;
// get the total body length
int requestLength = workerRequest.GetTotalEntityBodyLength();
// Get the initial bytes loaded
int initialBytes = 0;
if (workerRequest.GetPreloadedEntityBody() != null)
initialBytes = workerRequest.GetPreloadedEntityBody().Length;
if (!workerRequest.IsEntireEntityBodyIsPreloaded())
{
byte[] buffer = new byte[52000];
// Set the received bytes to initial bytes before start reading
int receivedBytes = initialBytes;
while (requestLength - receivedBytes >= initialBytes)
{
// Read another set of bytes
initialBytes = workerRequest.ReadEntityBody(buffer, buffer.Length);
// Update the received bytes
receivedBytes += initialBytes;
}
initialBytes = workerRequest.ReadEntityBody(buffer, requestLength - receivedBytes);
}
}
context.Response.Redirect("../UploadError.aspx");//Redirect to custom error page.
}
}- 已标记为答案 Alan.Deng 2010年4月1日 2:48
-
你好,
一般上述代码用来避免上传大文件时出现一些不可预测的错误的。
比如我们在web.config中配置了上传的最大限制,如果你超过了这个限制,你会看到一个似乎服务器没响应的页面,什么连接有问题的页面。
这时我们可以自定义一个HttpModule,调用花雨透提供的代码,对传过来的数据进行预处理,以避免出现上述情况。
在上面代码中,你可以选择保存该数据,也可以忽略它,但是必须要把传过来的数据过一遍,否则还是会报错。
即必须要至少要有下面这段代码:
while (requestLength - receivedBytes >= initialBytes) { // Read another set of bytes initialBytes = workerRequest.ReadEntityBody(buffer, buffer.Length); // Update the received bytes receivedBytes += initialBytes; }
你可以在上面的代码中保存数据。
建议你用花雨透 的方法试试。
Microsoft Online Community Support