ASP.NET 上传大文件(原创)

时间:2023-03-08 23:56:43
ASP.NET 上传大文件(原创)

问题描述

需要在网站中上传文件,但是当文件大小太大的时候IIS会拒绝连接,导致用户看到不友好的错误界面。

解决方法

1.服务器端处理

  在globle.asax中的protected void Application_Error(object sender, EventArgs e)函数中处理错误

  

    public class Global : System.Web.HttpApplication
{
static List<string[]> options;
static Global(){
var mlstr = WebConfigurationManager.AppSettings.Get("MaxRequestLength");
if (string.IsNullOrEmpty(mlstr)) options = null;
else
{
try
{
var optionstr = mlstr.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
options = new List<string[]>();
optionstr.ToList().ForEach(e => options.Add(e.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)));
}
catch(Exception e) { options = null; }
}
}
...
protected void Application_Error(object sender, EventArgs e)
{ if (Server.GetLastError().GetType() != typeof(HttpException)) return;
if (options == null) return;
var item = options.Find(i => i[] == this.Request.Url.LocalPath);
if (item == null) return; int maxRequestLength = ;
Int32.TryParse(item[], out maxRequestLength); //This code is used to check the request length of the page and if the request length is greater than
//MaxRequestLength then retrun to the same page with extra query string value action=exception HttpContext context = ((HttpApplication)sender).Context;
if (context.Request.ContentLength > maxRequestLength)
{
IServiceProvider provider = (IServiceProvider)context;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); // Check if body contains data
if (workerRequest.HasEntityBody())
{
// get the total body length
int requestLength = workerRequest.GetTotalEntityBodyLength();
// Get the initial bytes loaded
int initialBytes = ;
if (workerRequest.GetPreloadedEntityBody() != null)
initialBytes = workerRequest.GetPreloadedEntityBody().Length;
if (!workerRequest.IsEntireEntityBodyIsPreloaded())
{
byte[] buffer = new byte[];
// 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);
}
}
//Redirect the user to the same page with querystring action=exception.
//Response.ClearContent();
//context.Server.ClearError();
context.Response.Redirect(this.Request.Url.LocalPath + "?" + item[]);
}
}
...
}
<appSettings>
<add key="MaxRequestLength" value="/upload.ashx,100,errorcallback=upCallback"/>
</appSettings>

2.前端处理

  上传方式采用的是iframe仿ajax。因此考虑截获iframe的onload事件从而进行友好提示。

  但是经过测试:当服务器因连接长度过长断开连接时,firefox不会触发iframe的onload事件,因此该方法失败。

  http://src.chromium.org/svn/trunk/src/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js

  中第156行附近也说明了firefox没有好的截获connection reset事件的方式。

3.其他

其他诸如改变默认大小的方法不可取,因为无论多大,用户都可能选择超过你的设定。

结论

暂时采用方法一。如果firefox中可以截获connection reset事件,方法2明显优于方法1.

因为在方法一种会将上传文件全部读取(并不保存),消耗服务器资源。

原创于:http://www.cnblogs.com/errorx/

转载请注明