来源:http://www.cnblogs.com/HeroBeast/archive/2008/03/18/1084874.html
1.一般的在Asp.net里上传文件都是10m左右,要做到大文件上传,必须要改web.config,不过改了web.config有时候也上传不成功,那是每次上传的文件太大,浏览器在这个过程中会超时,采用分块上传的方法就可以避免这种情况。
2.分块上传就是利用post的方法,把数据分块上传,每块上传的数据量少,不会引起超时的问题。不说了,看代码吧。
using
System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Text;
using System.Globalization;
/// <summary>
/// 实现IHttpModule接口
/// </summary>
public class HttpUploadModule : IHttpModule
{
public HttpUploadModule()
{
}
public void Init(HttpApplication application)
{
// 订阅事件
application.BeginRequest += new EventHandler( this .Application_BeginRequest);
}
public void Dispose()
{
}
private void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
HttpWorkerRequest request = GetWorkerRequest(app.Context);
Encoding encoding = app.Context.Request.ContentEncoding;
int bytesRead = 0 ; // 已读数据大小
int read; // 当前读取的块的大小
int count = 8192 ; // 分块大小
byte [] buffer; // 保存所有上传的数据
if (request != null )
{
// 返回 HTTP 请求正文已被读取的部分。
byte [] tempBuff = request.GetPreloadedEntityBody(); // 要上传的文件
// 如果是附件上传
if (tempBuff != null && IsUploadRequest(app.Request)) // 判断是不是附件上传
{
// 获取上传大小
//
long length = long .Parse(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
buffer = new byte [length];
count = tempBuff.Length; // 分块大小
// 将已上传数据复制过去
//
Buffer.BlockCopy(tempBuff, // 源数据
0 , // 从开始读
buffer, // 目标容器
bytesRead, // 指定存储的开始位置
count); // 要复制的字节数。
// 开始记录已上传大小
bytesRead = tempBuff.Length;
// 循环分块读取,直到所有数据读取结束
while (request.IsClientConnected() && ! request.IsEntireEntityBodyIsPreloaded() && bytesRead < length)
{
// 如果最后一块大小小于分块大小,则重新分块
if (bytesRead + count > length)
{
count = ( int )(length - bytesRead);
tempBuff = new byte [count];
}
// 分块读取
read = request.ReadEntityBody(tempBuff, count);
// 复制已读数据块
Buffer.BlockCopy(tempBuff, 0 , buffer, bytesRead, read);
// 记录已上传大小
bytesRead += read;
}
if (request.IsClientConnected() && ! request.IsEntireEntityBodyIsPreloaded())
{
// 传入已上传完的数据
InjectTextParts(request, buffer);
}
}
}
}
HttpWorkerRequest GetWorkerRequest(HttpContext context)
{
IServiceProvider provider = (IServiceProvider)HttpContext.Current;
return (HttpWorkerRequest)provider.GetService( typeof (HttpWorkerRequest));
}
/// <summary>
/// 传入已上传完的数据
/// </summary>
/// <param name="request"></param>
/// <param name="textParts"></param>
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 );
}
}
private static bool StringStartsWithAnotherIgnoreCase( string s1, string s2)
{
return ( string .Compare(s1, 0 , s2, 0 , s2.Length, true , CultureInfo.InvariantCulture) == 0 );
}
/// <summary>
/// 是否为附件上传
/// 判断的根据是ContentType中有无multipart/form-data
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
bool IsUploadRequest(HttpRequest request)
{
return StringStartsWithAnotherIgnoreCase(request.ContentType, " multipart/form-data " );
}
}
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Text;
using System.Globalization;
/// <summary>
/// 实现IHttpModule接口
/// </summary>
public class HttpUploadModule : IHttpModule
{
public HttpUploadModule()
{
}
public void Init(HttpApplication application)
{
// 订阅事件
application.BeginRequest += new EventHandler( this .Application_BeginRequest);
}
public void Dispose()
{
}
private void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
HttpWorkerRequest request = GetWorkerRequest(app.Context);
Encoding encoding = app.Context.Request.ContentEncoding;
int bytesRead = 0 ; // 已读数据大小
int read; // 当前读取的块的大小
int count = 8192 ; // 分块大小
byte [] buffer; // 保存所有上传的数据
if (request != null )
{
// 返回 HTTP 请求正文已被读取的部分。
byte [] tempBuff = request.GetPreloadedEntityBody(); // 要上传的文件
// 如果是附件上传
if (tempBuff != null && IsUploadRequest(app.Request)) // 判断是不是附件上传
{
// 获取上传大小
//
long length = long .Parse(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
buffer = new byte [length];
count = tempBuff.Length; // 分块大小
// 将已上传数据复制过去
//
Buffer.BlockCopy(tempBuff, // 源数据
0 , // 从开始读
buffer, // 目标容器
bytesRead, // 指定存储的开始位置
count); // 要复制的字节数。
// 开始记录已上传大小
bytesRead = tempBuff.Length;
// 循环分块读取,直到所有数据读取结束
while (request.IsClientConnected() && ! request.IsEntireEntityBodyIsPreloaded() && bytesRead < length)
{
// 如果最后一块大小小于分块大小,则重新分块
if (bytesRead + count > length)
{
count = ( int )(length - bytesRead);
tempBuff = new byte [count];
}
// 分块读取
read = request.ReadEntityBody(tempBuff, count);
// 复制已读数据块
Buffer.BlockCopy(tempBuff, 0 , buffer, bytesRead, read);
// 记录已上传大小
bytesRead += read;
}
if (request.IsClientConnected() && ! request.IsEntireEntityBodyIsPreloaded())
{
// 传入已上传完的数据
InjectTextParts(request, buffer);
}
}
}
}
HttpWorkerRequest GetWorkerRequest(HttpContext context)
{
IServiceProvider provider = (IServiceProvider)HttpContext.Current;
return (HttpWorkerRequest)provider.GetService( typeof (HttpWorkerRequest));
}
/// <summary>
/// 传入已上传完的数据
/// </summary>
/// <param name="request"></param>
/// <param name="textParts"></param>
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 );
}
}
private static bool StringStartsWithAnotherIgnoreCase( string s1, string s2)
{
return ( string .Compare(s1, 0 , s2, 0 , s2.Length, true , CultureInfo.InvariantCulture) == 0 );
}
/// <summary>
/// 是否为附件上传
/// 判断的根据是ContentType中有无multipart/form-data
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
bool IsUploadRequest(HttpRequest request)
{
return StringStartsWithAnotherIgnoreCase(request.ContentType, " multipart/form-data " );
}
}
(1)修改web.config
<
httpModules
>
< add name ="up" type ="HttpUploadModule" />
</ httpModules >
< httpRuntime maxRequestLength ="2000000" executionTimeout ="300" />
< add name ="up" type ="HttpUploadModule" />
</ httpModules >
< httpRuntime maxRequestLength ="2000000" executionTimeout ="300" />
<
form
id
="form1"
runat
="server"
enctype
="multipart/form-data"
>
< div >
< asp:FileUpload ID ="FileUpload1" runat ="server" />
< asp:Button ID ="Button1" runat ="server" onclick ="Button1_Click" Text ="Button" />
</ div >
</ form >
< div >
< asp:FileUpload ID ="FileUpload1" runat ="server" />
< asp:Button ID ="Button1" runat ="server" onclick ="Button1_Click" Text ="Button" />
</ div >
</ form >
protected
void
Button1_Click(
object
sender, EventArgs e)
{
string strDesPath = " D:/ " ;
string strFileName = this .FileUpload1.PostedFile.FileName;
strFileName = strDesPath + strFileName; // .Substring(strFileName.LastIndexOf("/"));
//
this .FileUpload1.PostedFile.SaveAs(strFileName);
Response.Write( " 文件保存到了: " + strFileName);
}
{
string strDesPath = " D:/ " ;
string strFileName = this .FileUpload1.PostedFile.FileName;
strFileName = strDesPath + strFileName; // .Substring(strFileName.LastIndexOf("/"));
//
this .FileUpload1.PostedFile.SaveAs(strFileName);
Response.Write( " 文件保存到了: " + strFileName);
}
虽然可以上传大文件,但是这个大小也是有限制的,不能超过2G的大小。
本文介绍了一种在ASP.NET中实现大文件分块上传的方法,通过修改web.config配置并利用IHttpModule接口实现文件的分块读取与合并,有效解决了大文件上传过程中的超时问题。
1086

被折叠的 条评论
为什么被折叠?



