Jquery基于ActiveX的批量上传

本文介绍了一种客户端批量选择文件夹并上传图片至服务器的方法。利用JS构建本机文件目录,并通过将文件转换为Base64流的方式进行上传,解决了跨域问题及服务器端无法直接获取客户端文件路径的问题。

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

  由于技术和经验有限,我一直不敢把文章发到首页(除了第一次发文不清楚状况点错了之外)。这次壮着胆子喝了二两雪碧,我也豁出来了,大家看了要是觉得没什么技术含量的话,就当这篇文章是个小笑话也就是了~
  在做这个功能之前参考了很多网上的文章,能试的基本都试了,发现没有完全正确的,大部分也是转来转去的,比如:《JQuery+ajax实现批量上传图片》。实现的思想就是客户端选好了路径,传到服务器端接收然后实现上传。
  这样在本地做是没有任何问题的,(因为本地做服务器和客服端都是你自己的电脑)
而大部分的人看到这基本也不会真正的拿来用然后发布到网上,只是在本地练练手而已。

  但是一旦你发布之后,就会发现这个思路从根本上就是错的:用服务器端的方法接收客户端的文件路径,再用这个路径找文件,根本就找不到。因为服务器找到的是服务器本机的文件。(服务器和客户端已经分离)
而实现了这个功能的网站基本都找不到相应的实现细节,(比如曾经的网易网盘功能,还有现在的摇篮网的space空间上传)
  在这里抛砖引玉,希望大家一起讨论,也希望有网盘和批量上传经验的兄弟多多指点。


  先看看我要实现的功能和效果:(上传完毕会生成成功和失败两个文件夹)(这已经是我发布到内网服务器后的效果)


流程:
点击自动上传--弹出浮动窗口,展示本地磁盘--选择磁盘--列出该磁盘下所有文件夹--选择一个文件夹--点击确定--上传


  这里一个麻烦之处就是由于种种原因,你无法使用服务器端的fileupload控件或者客户端的input type=file控件
这样的话就无法在服务器端用Request.File接收文件,那该如何实现?

  由于用户要求选择文件夹而不是文件,所以我用不了任何控件,只能通过js构建本机文件目录,
最开始我使用了一个Jquery插件:jqueryFileTree。

  插件详细和下载请见:http://abeautifulsite.net/2008/03/jquery-file-tree/     。里面有使用说明和demo(英文,是个老外做的),老实说效果很好,只不过不适合我要实现的功能(用户选择服务器文件有何用?)
  实现原理是通过ajax在cs方法中构建目录串输出html。这里就遇到了之前提到的问题,用服务器方法只能获取服务器的文件路径,发布之后无效。所以无法通过ajax方式获取文件的html串,只能用纯js构建。
  我改造一下这个插件,这里要使用一个ActiveXObject:Scripting.FileSystemObject,是js中用来访问本机文件的插件。网上可以搜到这个插件下的方法和属性,但是不够全面,很多方法要通过自己调试js时查看变量方法和属性列表的方法找到。利用这个插件我改造了jqueryFileTree,让它变成一个纯js访问本机文件目录。

  注:此ActiveXObject的用法参照了这篇文章:http://www.cnblogs.com/dwjaissk/archive/2007/02/28/659153.html

里面有很多Scripting.FileSystemObject下面的方法和属性。


  主要改造了showTree方法:

 

   ExpandedBlockStart.gif filetree
    function  showTree(c, t) {
                    $(c).addClass(
' wait ' );
                    $(
" .jqueryFileTree.start " ).remove();
                    
var  a  =   new  Array;
                    t 
=  unescape(t);
                    
var  fso, f, fc, a;
                    fso 
=   new  ActiveXObject( " Scripting.FileSystemObject " );

                    $(
' #inputpath ' ).val(t);
                    f 
=  fso.GetFolder(t);
                    fc 
=   new  Enumerator(f.SubFolders);

                    
for  (;  ! fc.atEnd(); fc.moveNext()) {
                        a[a.length] 
=  fc.item();
                    }
                    a 
=  (a);
                    
for  ( var  i  =   0 ; i  <  a.length; i ++ ) {
                        
var  str  =   " <ul class='jqueryFileTree' style='display: none;'><li class='directory collapsed'><a href='#' rel=' "   +  a[i]  +   " /'> "   +  a[i]  +   " </a></li></ul> " ;
                        $(c).removeClass(
' wait ' ).append(str);
                    }
                    
if  (a.length  <   1 ) {
                        $(c).removeClass(
' wait ' );
                    }
                    $(c).find(
' .start ' ).html( '' );
                    
if  (o.root  ==  t) $(c).find( ' UL:hidden ' ).show();
                    
else  $(c).find( ' UL:hidden ' ).slideDown({ duration: o.expandSpeed, easing: o.expandEasing });

                    bindTree(c);
                }

 

 

ExpandedBlockStart.gif 前台html
< form  id ="form1"  runat ="server" >
    
< div >
    
         
< div  style ="width:978px;padding:1px;margin:10px auto;background:#00a8fe;" >
        
< div  style ="border:1px solid #fff;font-size:14px;" >
        
< div  style ="background:#edf9ff;height:35px;padding:0 15px 0 15px;line-height:35px" >
            照片上传:
< input  id ="File1"  runat ="server"  name ="File1"   size ="44"  type ="file"   />    
            
< asp:Button  ID ="Button_upload"  runat ="server"  Text ="上 传"    onclick ="Button_upload_Click"   />                   
                        
< input  id ="chkAutoUpload"  type ="checkbox"  onclick ="showOrhidden()"   /> 自动上传 &nbsp;
                
</ div >
        
</ div >
    
    
</ div >
    
    
<% -- 浮动层 -- %>
    
< div  id ="divfloat" >
        
< id ="closeX"  href ="javascript:closethis()"  onmouseover ="this.innerHTML='关闭'"  onmouseout ="this.innerHTML='×'" > × </ a >  
        
< div  id ="divaddfirst" >
           
            
< input  id ="lblselect"  class ="inputlbl"  type ="text"  value ="选择需上传图片所在的文件夹"   />
             
< input  id ="lblweb"  style ="width:230px;"  disabled ="disabled"  class ="inputlbl"  type ="text"  value ="(此功能需要加本站点为可信任站点)"   />< br  />
            
< span  style ="color:Red; font-size:14px;" > 您选择的上传图片所在路径为: </ span >
            
            
            
< input  id ="inputpath"  class ="inputlbl"  type ="text"  value =""  disabled ="disabled"   style =" width:320px;font-weight:bold; font-size:16px;"   />
            
< input  type ="checkbox"  id ="chkIsTj"   /> 特检照片
            
< ul >
            
< li  id ="liC"  class ="diskli" >
                
< img  src ="Images/FolderImg/disk.jpg"  alt =""  onclick ="choosefolder('C')"  style ="cursor:hand;"   />
                
< id ="hrefC"  style ="color:Black; font-size:medium "   href ="javascript:choosefolder('C')" > 本地磁盘 (C:) </ a >
                
< div  id ="divContainerC"  class ="divContainer" ></ div >
            
</ li >
            
< li  id ="liD"  class ="diskli" >
                
< img  src ="Images/FolderImg/disk.jpg"  alt =""  onclick ="choosefolder('D')"  style ="cursor:hand;"   />
                
< id ="hrefD"  style ="color:Black; font-size:medium "   href ="javascript:choosefolder('D')" > 本地磁盘 (D:) </ a >
                
< div  id ="divContainerD"  class ="divContainer" ></ div >
            
</ li >
            
< li  id ="liE"  class ="diskli" >
                
< img  src ="Images/FolderImg/disk.jpg"  alt =""  onclick ="choosefolder('E')"  style ="cursor:hand;"   />
                
< id ="hrefE"  style ="color:Black; font-size:medium "   href ="javascript:choosefolder('E')" > 本地磁盘 (E:) </ a >
                
< div  id ="divContainerE"  class ="divContainer" ></ div >
            
</ li >
            
</ ul >
             
< href ="javascript:selectconfirm()"  style =" position:absolute; bottom:20px; left:300px; font-size:16px; font-weight:bold;" > 选择完毕 </ a >
            
< input  id ="input2"  class ="inputlbl"  type ="text"  value ="上传中,关闭当前页将停止上传...上传日志信息保存在网站根目录下Logs\AutoUploadPhoto_Exception.txt"  disabled ="disabled"   style =" display:none;position:absolute; bottom:10px; left:20px; width:600px; color:Red;"   />
            
< input  id ="hidinput"  style ="display:none;"  value ="0"   />  
        
</ div >
    
</ div >
    
< div  id ="divfloatbg" ></ div >
    
</ div >
    
</ form >

 

 

  浮动效果的实现网上有很多,方法:

ExpandedBlockStart.gif 浮动
//悬浮层显示
        function showOrhidden()
        {
            var w = document.documentElement.clientWidth; //宽
            var h = document.documentElement.clientHeight; //高
            var tw = $("#divfloat").width();
            var th = $("#divfloat").height();
            $("#divfloat").css({ "position": "absolute", "top": h / 2 - th / 2, "left": w / 2 - tw / 2 });
            if ($("#chkAutoUpload").attr("checked") == true)
            {
                $("#divfloatbg").css("opacity", "0.5"); //透明度
                $("#divfloatbg").fadeIn("slow"); //缓慢淡出
                $("#divfloat").fadeIn("slow");
            }
            else
            {
                $("#divfloatbg").fadeOut("slow");
                $("#divfloat").fadeOut("slow");
            }
        }

 

 

  点击文件夹按钮事件:

ExpandedBlockStart.gif 代码
  // 选择本地文件夹上传相片
         function  choosefolder(disk)
        {
            $(
" .divContainer " ).html( "" );  // 清空
             var  divContainer  =   ' #divContainer '   +  disk;
            
// 构建div目录树
            $(divContainer).fileTree({ root: disk  +   ' :\\ ' , multiFolder:  false  },  function (file)
            {
                
// alert(file);
            });
        }

 

  改造好之后已经可以实现这样的功能:传入一个盘符号,会列出所有该盘符的所有文件夹,继续点击会继续列出相应文件夹的子文件夹(和windows文件效果类似)。


  接下来要实现上传。没有控件就不能直接接受file,又不能接收路径查找文件,那么只能把文件整个传到服务器端。思路是将文件转成base64流,再通过ajax传到服务器端(这里要用到另一个插件MSXML2.DOMDocument),然后服务器端Request.InputStream接收,然后用XML处理这个流,之后base64解码,然后继续你的上传流程就可以了。

ExpandedBlockStart.gif 代码
// 选择完成后确定按钮事件
         function  selectconfirm()
        {
            
var  localpath  =  $( " #inputpath " ).val();
            
var  leaving  =  $( " #LblYue " ).text();
            
var  tj  =  $( " #chkIsTj " ).attr( " checked " ==   true   ?   " 1 "  :  " 0 " ;
            $(
" #input2 " ).show();
            $(
" #hidinput " ).val( " 1 " );
            upload(localpath, leaving, tj);
        }
    
    
        
// 上传和文件夹操作
         function  upload(localpath, leaving, tj)
        {
            
var  fso, f, fc, a;
            fso 
=   new  ActiveXObject( " Scripting.FileSystemObject " );
            f 
=  fso.GetFolder(localpath);

            
if  ( ! fso.FolderExists(localpath  +   " \\Success " ))
            {
                fso.CreateFolder(localpath 
+   " \\Success " );
            }
            
if  ( ! fso.FolderExists(localpath  +   " \\Fail " ))
            {
                fso.CreateFolder(localpath 
+   " \\Fail " );
            }

            ff 
=   new  Enumerator(f.files);
            
for  (;  ! ff.atEnd(); ff.moveNext()) // 枚举所有文件   
            {
                s 
=  ff.item();    // 取文件对象
                alert(s);
                uptowebmethod(s.Path, leaving, tj, f.Path, localpath);
            }
        }
        
        
// 文件->流->XML->ajax传入后台
         function  uptowebmethod(path, leave, istj, fpath, localpath)
        {
            
var  ado_stream  =   new  ActiveXObject( " ADODB.Stream " );
            
var  xml_dom  =  createXMLDOM();

            xml_dom.loadXML(
' <?xml   version="1.0" ?><root/> ' );
            xml_dom.documentElement.setAttribute(
" xmlns:dt " " urn:schemas-microsoft-com:datatypes " );
            
var  l_node1  =  xml_dom.createElement( " photo " );
            l_node1.dataType 
=   " bin.base64 " ;

            ado_stream.Type 
=   1 ;    //    1=adTypeBinary     
            ado_stream.Open();
            ado_stream.LoadFromFile(path);

            l_node1.nodeTypedValue 
=  ado_stream.Read( - 1 );    //    -1=adReadAll   
            ado_stream.Close();
            xml_dom.documentElement.appendChild(l_node1);

            
var  pnode  =  xml_dom.createElement( " path " );
            xml_dom.documentElement.appendChild(pnode);
            pnode.text 
=  path;

            
var  lnode  =  xml_dom.createElement( " leave " );
            xml_dom.documentElement.appendChild(lnode);
            lnode.text 
=  leave;

            
var  tjnode  =  xml_dom.createElement( " istj " );
            xml_dom.documentElement.appendChild(tjnode);
            tjnode.text 
=  istj;

            
var  fnode  =  xml_dom.createElement( " fpath " );
            xml_dom.documentElement.appendChild(fnode);
            fnode.text 
=  fpath;


            $.ajax({
                type: 
" POST " ,    // 访问WebService使用Post方式请求
                 // contentType: "application/json", //WebService 会返回Json类型
                url:  " AjaxForm1.aspx " // 调用WebService的地址和方法名称组合 ---- WsURL/方法名
                processData:  false ,
                data: xml_dom,    
// 这里是要传递的参数,格式为 data: "{paraName:paraValue}",下面将会看到
                 // dataType: 'json',
                success:  function (result)
                {     
// 回调函数,result,返回值
                     if  (result  ==   ' 0 ' )
                    {
                        s.move(localpath 
+   " \\Fail\\ "   +  s.name);
                    }
                    
else   if  (data  ==   ' 1 ' )
                    {
                        s.move(localpath 
+   " \\Success\\ "   +  s.name);
                    }
                    
else
                    {
                        alert(result);
                    }
                }
            })
        }

        
// 创建XMLDOM
         function  createXMLDOM()
        {
            
var  arr  =  [ " MSXML2.DOMDocument.5.0 " " MSXML2.DOMDocument.4.0 " " MSXML2.DOMDocument.3.0 " " MSXML2.DOMDocument " " Microsoft.XmlDom " ];
            
for  ( var  i  =   0 ; i  <  arr.length; i ++ )
            {
                
try
                {
                    
var  xmlDom  =   new  ActiveXObject(arr[i]);
                    
return  xmlDom;
                }
                
catch  (oError)
                {
                    alert(
" error " );
                }
            }
            
throw   new  Error( " MSXML is not install on your system. " );
        }

 

   服务器端主要代码:

  

 

ExpandedBlockStart.gif 代码
#region  Page_Load
        
protected   void  Page_Load( object  sender, EventArgs e)
        {
            Stream photoStream 
=  Request.InputStream;
            XmlDocument doc 
=   new  XmlDocument();

            
if  (Request.InputStream  !=   null )
            {
                
// byte[] _tmpData = new byte[photoStream.Length];
                
// photoStream.Read(_tmpData, 0, Convert.ToInt32(photoStream.Length));
                
// string request1 = System.Text.Encoding.UTF8.GetString(_tmpData); 



                doc.Load(photoStream);
                XmlNode nod 
=  doc.DocumentElement.SelectSingleNode( " path " );
                Paths 
=  nod.InnerText;

                nod 
=  doc.DocumentElement.SelectSingleNode( " fpath " );
                
string  fpath  =  nod.InnerText;

                nod 
=  doc.DocumentElement.SelectSingleNode( " leave " );
                
string  leaving  =  nod.InnerText;

                nod 
=  doc.DocumentElement.SelectSingleNode( " istj " );
                
string  istj  =  nod.InnerText;

                
string  photoXML  =  doc.DocumentElement.SelectSingleNode( " photo " ).InnerText;

                
byte [] photo  =  Convert.FromBase64String(photoXML);


                
// 去除xml中的多余标签和属性,转化为stream
                MemoryStream stream  =   new  MemoryStream();
                XmlDocument docphoto 
=   new  XmlDocument();
                
char [] str  =  photoXML.ToCharArray();
                
for  ( int  i  =   0 ; i  <  photo.Length; i ++ )
                {
                    stream.WriteByte(photo[i]);
                }
                docphoto.Save(stream);


                
if  ( ! string .IsNullOrEmpty(Paths))
                {
                    
// 存入cookie
                    HttpCookie cookie  =  Request.Cookies[ " Path " ];
                    
if  (cookie  ==   null )
                    {
                        cookie 
=   new  HttpCookie( " Path " );
                    }
                    cookie[
" path " =  fpath;
                    cookie[
" istj " =  istj;
                    cookie.Expires 
=  DateTime.Now.AddDays(100d);
                    Response.Cookies.Add(cookie);

                    UploadPh(Paths, leaving, istj, stream);//在此方法处理你的上传
                }
            }
        }
#endregion

 

  目前此方法有三大问题:
  1.不同的浏览器安全级别略有区别,activex经常会弹出提示,影响用户体验,有的还需要用户设置本站点为信任站点。
  2.除IE外别的浏览器无法使用
  3.IE有一个补丁对ADODB.Stream进行了限制使用,如果你一直开了自动更新或打了这个补丁,会弹出js错误:automation无法在服务器创建。其实就是ADODB.Stream无法创建对象造成的。
  解决方法:打开注册表编辑器
  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\
把{00000566-0000-0010-8000-00AA006D2EA4} 项删除或修改键值为任意值(除了400),这样你的ADODB.Stream就可以创建成功了。

  css我就不贴了。大家有什么好的方案尽管拿出来~


 

转载于:https://www.cnblogs.com/dzxw2371/archive/2009/12/30/1636052.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值