IHttpModule 分块上传大文件

IHttpModule 分块上传大文件

来源: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");

}

}

3.用法

(1)修改web.config

<httpModules>

<add name="up" type="HttpUploadModule"/>

</httpModules>

<httpRuntime maxRequestLength="2000000" executionTimeout="300" />

(2)aspx

<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>

(3)aspx.cs

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);

}

4.大文件上传的限制

虽然可以上传大文件,但是这个大小也是有限制的,不能超过2G的大小。

分类: VS2005

绿色通道: 好文要顶 关注我 收藏该文与我联系

C# 大文件上传的更多相关文章

  1. 解决PHP大文件上传问题

    PHP大文件上传问题    今天负责创业计划大赛的老师问我作品上报系统上传不了大文件,我当时纳闷了,做的时候没限制上传文件的大小阿,怎么会传不了呢,自己亲自体验了番,果然不 行,想了好一会儿才有点眉目 ...

  2. 使用commons-fileupload包进行大文件上传注意事项

    项目中使用 commons-fileupload-1.2.1.jar 进行大文件上传. 测试了一把,效果很不错. 总结如下: 必须设置好上传文件的最大阀值 final long MAX_SIZE = ...

  3. 因用了NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误的解决方法

    今天遇到一个问题,就是“NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误”,百度后发现了一个解决方法,跟大家分享下: NeatUploa ...

  4. ASP.NET 大文件上传的简单处理

    在 ASP.NET 开发的过程中,文件上传往往使用自带的 FileUpload 控件,可是用过的人都知道,这个控件的局限性十分大,最大的问题就在于上传大文件时让开发者尤为的头疼,而且,上传时无法方便的 ...

  5. 【原创】用JAVA实现大文件上传及显示进度信息

    用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 (本文提供全部源码下载,请访问 https://github.com/grayprince/UploadBigFil ...

  6. BootStrap Progressbar 实现大文件上传的进度条

    1.首先实现大文件上传,如果是几兆或者几十兆的文件就用基本的上传方式就可以了,但是如果是大文件上传的话最好是用分片上传的方式.我这里主要是使用在客户端进行分片读取到服务器段,然后保存,到了服务器段读取 ...

  7. 使用NeatUpload控件实现ASP.NET大文件上传

    使用NeatUpload控件实现ASP.NET大文件上传 一般10M以下的文件上传通过设置Web.Config,再用VS自带的FileUpload控件就可以了,但是如果要上传100M甚至1G的文件就不 ...

  8. Asp.net mvc 大文件上传 断点续传

    Asp.net mvc 大文件上传 断点续传 进度条   概述 项目中需要一个上传200M-500M的文件大小的功能,需要断点续传.上传性能稳定.突破asp.net上传限制.一开始看到51CTO上的这 ...

  9. 百万行mysql数据库优化和10G大文件上传方案

    百万行mysql数据库优化和10G大文件上传方案 最近这几天正在忙这个优化的方案,一直没时间耍,忙碌了一段时间终于还是拿下了这个项目?项目中不要每次都把程序上的问题,让mysql数据库来承担,它只是个 ...

  10. Nginx集群之WCF大文件上传及下载(支持6G传输)

    目录 1       大概思路... 1 2       Nginx集群之WCF大文件上传及下载... 1 3       BasicHttpBinding相关配置解析... 2 4       编写 ...

随机推荐

  1. 一次mysql 优化 (Using temporary ; Using filesort)

    遇到一个SQL执行很慢 SQL 如下: SELECT ... FROM tableA WHERE time >= 1492044535 and time <= 1492046335 GRO ...

  2. struts2 自己定义表单

    自己定义表单一定会涉及<s:iterator/>迭代,一个复杂的自己定义表单可能会嵌套n多层迭代. 比方一个自己定义一个问卷调查页面涉及3个模型:一个Survey代表一个调查.一个Page ...

  3. LUA协程复用

    -----协程复用根函数 local function routine(fun, args) while (fun) do fun, args = coroutine.yield(fun(table. ...

  4. PHP swfupload图片上传实例

    swfupload已经是第二次研究,这次自已整了个简单demo,无奈菜鸟最杯… PHP代码如下: if (isset($_FILES["Filedata"]) || !is_upl ...

  5. 分享:APK高级保护方法解析(三)

    刷朋友圈.玩游戏.看新闻,智能手机正在以我们无法想象的速度飞快发展,可是随之而来的安全问题也越来越引人关注,APP二次打包.反编译.盗版的现象屡见不鲜.因此须要对APK进行加固保护. 眼下市面上常见的 ...

  6. git 删除目录

    1. 查看本地已经被删除的文件 2. 删除 目录以及目录下的文件 [root@test01 h2_mopub_replace]# git rm ../test_code_driver -r 3. [r ...

  7. Random产生随机数问题

    昨天在开发时发现这个问题,在同一个for循环内,通过Random多次产生随机数得到的随机数竟是一样的!以前还真没发现这个问题. 以下是简化的代码,如果将random定义在for循环外面则不会有问题(猜 ...

  8. Boost中的Timer的使用——计算时间流逝

    使用Boost中的Timer库计算程序的运行时间 程序开发人员都会面临一个共同的问题,即写出高质量的代码完毕特定的功能.评价代码质量的一个重要标准就是算法的运行效率,也就是算法的运行时间.为了可靠的提 ...

  9. BZOJ 3550 ONTAK2010 Vacation 单纯形

    题目大意:给定一个长度为3n的区间.要求选一些数,且随意一段长度为n的区间内最多选k个数.求选择数的和的最大值 单纯形直接搞 注意一个数仅仅能被选一次 因此要加上xi<=1这个约束条件 不明确3 ...

  10. 如何用DOS命令,获取一个目录下的文件数目

    发信人: GOOGOODALLS (我爱Figo), 信区: DOS 标  题: 如何用DOS命令,获取一个目录下的文件数目? 发信站: 水木社区 (Fri Mar  9 08:40:01 2007) ...