asp.net分块上传大文件

转自 http://blog.163.com/soldier_200/blog/static/1552123320091115319532/


sp.net分块上传大文件

1.一般的在Asp.net里上传文件都是10m左右,要做到大文件上传,必须要改web.config,不过改了web.config有时候也上传不成功,那是每次上传的文件太大,浏览器在这个过程中会超时,采用分块上传的方法就可以避免这种情况。
2.分块上传就是利用post的方法,把数据分块上传,每块上传的数据量少,不会引起超时的问题。不说了,看代码吧。
Code

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;

namespace Web
{
    //实现IHttpModule接口
    public class HttpUploadModule : IHttpModule
    {
        public HttpUploadModule() { }
        public void Dispose()
        {
        }

        public void Init(HttpApplication application)
        {
            //订阅事件
            application.BeginRequest += new EventHandler(this.Application_BeginRequest);
        }

        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,                      //从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

  <system.web>
    <httpModules>
      <add type="HttpModelApp.HttpUploadModule, HttpModelApp" />
    </httpModules>
    <httpRuntime maxRequestLength="2000000"       executionTimeout="300" />
  </system.web>

(2)aspx

    <form runat="server" enctype="multipart/form-data" method="post">
        <div>
            <input type="file" runat="server"><br />
            <asp:Button runat="server" Text="上传" /><br />
            <asp:Label runat="server"></asp:Label>
        </div>
    </form>

 (3)aspx.cs

        protected void Button1_Click(object sender, EventArgs e)
        {
            //要保存的位置
            string strDesPath = "D:\\";
            string strFileName = this.firstFile.PostedFile.FileName;
            strFileName = strDesPath + strFileName.Substring(strFileName.LastIndexOf("\\"));
            //
            this.firstFile.PostedFile.SaveAs(strFileName);
            this.Label1.Text = "文件保存到了:" + strFileName;
        }

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


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值