zoukankan      html  css  js  c++  java
  • 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的大小。

  • 相关阅读:
    数组中最大和的子数组
    数据结构与算法面试题80道
    fcntl获取和修改文件打开状态标志
    dup等复制文件描述符函数
    截断文件函数truncate和ftruncate
    浅析
    五个Taurus垃圾回收compactor优化方案,减少系统资源占用
    如何用交互式特征工程工具进行数据分析处理
    【华为云技术分享】解密如何使用昇腾AI计算解决方案构建业务引擎
    Scrum Master教你四招,瓦解团队内部刺头
  • 原文地址:https://www.cnblogs.com/xjyggd/p/1374772.html
Copyright © 2011-2022 走看看