asp.net多个大文件上传的求解?

本文介绍了一个复杂的文件夹上传功能实现过程,包括使用ActiveX控件选择文件夹、自动生成表单上传文件信息、解决大文件上传问题等。通过实现IHttpModule接口改变IIS接收文件方式,成功支持大文件上传。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做个上传整个文件夹的功能,这个东西看似简单,但以前没接触过,费了我好大力气。最终勉勉强强可以实现了。

我看这个功能采用一个activex控件会省事很多。

步骤:点击浏览,选择文件夹---然后上传

选择文件夹我采用自制的activex控件,这步在前几篇文章中提到过了。

选择了文件夹后,返回了所有文件路径和空文件夹路径,我需要采用自动生成input表单来传递上传文件信息,空文件夹采用后台创建而不是上传了。

表单自动生成代码:<div id=MyZone></div>

WshShell=new ActiveXObject("WScript.Shell");
              createinputs();

//自动创建表单
            function createinputs()
            {
                var i=1;
                var formhtml="";
                for(i;i<=filecnt+1;i++)
                {
                    //创建表单代码              
                    formhtml+="<input type='file' size='1' name='uploadfile"+i+"'><br>";//创建表单代码
                }
                document.all.MyZone.innerHTML=formhtml;
               
                s = setInterval("setfile(start)",10);
            }
            //表单赋值代码(模拟复制粘贴)
            function setfile(j)
            {
                if (start==(filecnt+1))
                {               
                 window.clipboardData.setData('text',"end");
                 eval("document.all.uploadfile"+j).focus();
                 WshShell.sendKeys("^a");
                 WshShell.sendKeys("^v");
                
                 window.clipboardData.setData('text',document.all.TextBox1.Text);
                 eval("document.all.TextBox1").focus();
                 WshShell.sendKeys("^a");
                 WshShell.sendKeys("^v");
                }
                else
                {
                    //alert(document.all.backserverstr.value);
                 var filearr = document.all.backserverstr.value.split("*");
                 //alert(start);
                 //alert(filearr[j-1]);
                 window.clipboardData.setData('text',filearr[j-1]);
             
             eval("document.all.uploadfile"+j).focus();
             //WshShell.sendKeys("中国");//filearr[j-1]);
            
             WshShell.sendKeys("^a");//Ctrl + A 操作
                WshShell.sendKeys("^v");//Ctrl + V 操作(sendKeys对于中文赋值操作显得无力,所以只能模拟键盘操作)
                }
             start++;            
             if (start==(filecnt+1+1)){clearInterval(s);document.all.submitbtn.click();start=1;}
            }

表单生成后要给其赋值,因为WshShell=new ActiveXObject("WScript.Shell");对象不支持中文路径,所以采用模拟键盘输入的方法,也就是复制粘贴的方法,呵呵,挺搞笑的,这是网上一位老兄想出来。其实可以下载一个dll来支持中文,麻烦,又要做activex,我可不想再整了。

还有一个问题是,这些表单显示在页面上不太美观,要模拟键盘赋值所以不能设置为不可见,我试图找一种遮罩的东西,但没有找到,希望哪位仁兄给点建议,具体点。后来瞎整,把<div id=MyZone></div>放到一个table里面,奇迹般的不显示了,我也不深究了,因为为这个功能我花了太多时间了,进度紧得很,时间不允许了。

还有一个问题是,要将form中属性增加encType="multipart/form-data" ,这样才能提交多个文件。

大文件问题,asp.net单个文件上传的大小默认是4m,要修改web.config中的<httpRuntime executionTimeout="500" maxRequestLength="2000000" />。

加了这个还是不能传太大的(没有验证),可以修改iis上传后处理的方式,即实现IHttpModule接口。

/// <summary>
    /// iis接受上传分块文件
    /// 此类继承IHttpModule接口,改变iis接受文件的方式,从而可以接受大文件上传
    /// 使用此类只需要修改【1】web.config:
    /// <system.web>     
    ///     <!--
    ///         大文件上传处理:分块上传
    ///     -->
    ///     <httpModules>       
    ///         <add name="HttpUploadModule" type="WebGeoDBSys.HttpUploadModule, WebGeoDBSys"/>
    ///     </httpModules>
    ///     <!-->
    ///         设置文件上传的大小限制,默认是4M
    ///     -->
    ///     <httpRuntime executionTimeout="500" maxRequestLength="2000000" />
    /// </summary>
    /// 【2】在页面的html中form中修改属性enctype="multipart/form-data"
    ///
    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));


                    //文件不能太大,只能在这个范围左右
                    if (length < 250000000)
                    {

                        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, System.Globalization.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");
        }


       
    }

没想到这么麻烦。

 

以前采用的ftp路径直接访问,然后拷贝文件到该目录的方法虽然不太友好,但挺实用的。

我认为做个ftp 上传的activex组件应该会更加方便点。

待以后再去修改吧。

转载于:https://www.cnblogs.com/penglink/archive/2009/04/02/1427933.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值