关闭

asp jscript 调用 asp vbscript class/类, by shawl.qiu

标签: aspvbscriptfunctionextensionclassserver
2976人阅读 评论(0) 收藏 举报
分类:

 asp jscript 调用 asp vbscript class/类, by shawl.qiu


说明:
在鄙人的前一篇文章里实现了 jscript 与 vbscript 的互访.
详见:
http://blog.csdn.net/btbtd/archive/2007/09/15/1785817.aspx

那么, 居然能互访了, 我想应该做点什么.
嗯, 对了, jscript 是没有 二进制函数的, 所以嘛, jscript 基本上不能写 上传类...
不过可以通过调用 vbscript 的二进制函数达到目的, 但那样太过于繁琐.
那咋办..哦, 因鄙人以前用 asp vbscript 写过一个完整的上传类.
所以嘛, 有现成的, 赶紧试试...

在测试的过程中, 问题就来了.
因为 jscript 根本就没有与 vbscript class 对应的数据类型...
呵呵, 真难搞呀, 不过..
在经过一小番思考之后, 有了, 咱用一个函数实体化 vbscript 类 再返回 不就得了...
一试之后, 果然见效...

剩下的, 留给代码说说.

目录:
1. 实现一个简单的类(foo
1.1 vbscript_class.asp
1.2 jscript_call.asp

2. 调用 vbscript sqUpload 类
2.1 sqUpload(Lib).asp
2.2 sqUpload.inc

shawl.qiu
2007-09-15
http://blog.csdn.net/btbtd

下载:
http://files.myopera.com/btbtd/web/Jscript_call_Vbscript_class.7z

内容:
1. 实现一个简单的类(Foo)
1.1 vbscript_class.asp
<%
 'dim ins
 
 'set ins = new Foo
 'ins.Show()
 'ins = null 
  
 '---------------------------------------------------------------------'
 ' shawl.qiu 类 v
 '---------------------------------------------------------------------'
 '---------------------------------------------------------------------begin class Foo
 class Foo
  '------------------------------------begin event
  private sub class_initialize()
   auSubject=""
   auVersion="v1.0"
   au="shawl.qiu"
   auEmail="shawl.qiu@gmail.com"
   auBlog="http://blog.csdn.net/btbtd"
   auCreateDate="2007-1-21"
  end sub
  
  private sub class_terminate()
  
  end sub
  '------------------------------------end event
  
  '------------------------------------begin public variable
  '---------------begin about
  public auSubject, auVersion, au, auEmail, auBlog, auCreateDate
  '---------------end about
  '------------------------------------end public variable
  
  '------------------------------------begin public method
  
  '------------------------------------end public method
  
  '------------------------------------begin private variable
  function Show
   Response.Write("auSubject: "+auSubject+"<br/>")
   Response.Write("auVersion: "+auVersion+"<br/>")
   Response.Write("au: "+au+"<br/>")
   Response.Write("auEmail: "+auEmail+"<br/>")
   Response.Write("auBlog: "+auBlog+"<br/>")
   Response.Write("auCreateDate: "+auCreateDate+"<br/>")
  end function
  '------------------------------------end private variable
  
  '------------------------------------begin private method
  
  '------------------------------------end private method
 end class
 '---------------------------------------------------------------------end class Foo
 
 function FooVbs()
  Set FooVbs = new Foo
 end function 

%>


1.2 jscript_call.asp
<%@LANGUAGE="JAVASCRIPT" CODEPAGE="65001"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>shawl.qiu template</title>
</head>
<body>
<%
 var Ar = fStream("vbscript_class.asp""utf-8"true);
 Ar[0= Ar[0].replace(/</%|/%/>/g, "");
 //Response.Write("<xmp>"+Ar+"</xmp>");
 fLoadingVbs(Ar[0]);
 
 Response.Write("typeof foo: "+(typeof foo)+"<br/>");
 Response.Write("typeof FooVbs: "+(typeof FooVbs)+"<br/>");
 //fVarName(Foo) // Foo is not found
 Response.Write("<hr/>");
  
 var ins = FooVbs();
 ins.Show();
 ins = null;

 function fStream(sPath, sCharset, bCov)
 { // shawl.qiu code, return array
  if(bCov) sPath = Server.MapPath(sPath);
  var Stream = new ActiveXObject("Adodb.Stream");
  Stream.Type = 2;
  Stream.Mode = 3;
  Stream.Open;
  Stream.LoadFromFile(sPath);
  
  if(sCharset) Stream.CharSet = sCharset;
  var iStep =0;
  if(/utf/s*/-/s*8|unicode/i.test(sCharset)) iStep = 2;
  Stream.Position = iStep;
  var Ar = [Stream.ReadText()];
  delete Stream;
  return Ar;
 } // end function fStream(sPath, sCharset)

%>
<script runat="server" language="vbscript">
 function fLoadingVbs(Ar)
  ExecuteGlobal Ar
 end function
 
 function fVarName(VarName)
  Response.Write("TypeName(VarName): "+TypeName(VarName)+"<br/>")
 end function
</script>
</body>
</html>


2. 调用 vbscript sqUpload 类
2.1 sqUpload(Lib).asp
<%@LANGUAGE="JAVASCRIPT" CODEPAGE="65001"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>shawl.qiu template</title>
</head>
<body>
<% 
 var Ar = fStream("sqUpload.inc""utf-8"true);
 Ar[0] = Ar[0].replace(/</%|/%/>/g, "");
 //Response.Write("<xmp>"+Ar+"</xmp>");

 function fStream(sPath, sCharset, bCov)
 { // shawl.qiu code, return array
  if(bCov) sPath = Server.MapPath(sPath);
  var Stream = new ActiveXObject("Adodb.Stream");
  Stream.Type = 2;
  Stream.Mode = 3;
  Stream.Open;
  Stream.LoadFromFile(sPath);
  
  if(sCharset) Stream.CharSet = sCharset;
  var iStep =0;
  if(/utf/s*/-/s*8|unicode/i.test(sCharset)) iStep = 2;
  Position = iStep;
  var Ar = [Stream.ReadText()];
  delete Stream;
  return Ar;
 } // end function fStream(sPath, sCharset)
 
 fLoadingVbs(Ar[0]);
 
 var up = sqUploadVbs();
  up.debug=false;         
  up.item=5;               
  up.action="?id=ufile";         
  up.totalsize=1024*10;
  up.singlesize=1024;
  up.path="/uploads/";           
  
  up.extension="7z,rar,zip,mp3,bmp,gif,jpg,jpeg,png,txt,swf,html,htm";
  up.charset="utf-8";
  
  up.interval=30;           
  up.gobackSecond=10;            
  up.gobackurl="?";           
  
  up.prefix="";             
  up.autorename=false;           
  up.rndpostfix=false;          
  
  up.ckeckfile=true;          
  
  up.listForCheck="jpg,gif,png,jpeg"
  
  up.autoRenameOpt=true;
  up.prefixOpt=true;        
  up.rndPostfixOpt=true;         
  
  up.header();                     
  
  if(Request.QueryString("id")+""=="ufile")
  {
   up.exec();                    
   up.report()
  }            
  
  up.info();
  up.form();
  up.about();                      
  up.footer();   
   
  up = null;
%>

<script runat="server" language="vbscript">
 function fLoadingVbs(Ar)
  ExecuteGlobal Ar
 end function
</script>
</body>
</html>


2.2 sqUpload.inc
<%
' dim up
' set up=new sqUpload
'  up.debug=false                '非必选, 调试时 设为 true 
'  up.item=5                     '必选项, 显示多少个上传文件域'
'  up.action=SQSTRINGMARKER0         '必选项, 上传提交路径
'  up.totalsize=1024*10 'kb'     '必选项, 上传总大小
'  up.singlesize=1024 'kb        '必选项, 上传每文件总大小 
'  up.path=SQSTRINGMARKER1           '必选项, 上传目录
'  
'  '必选项, 允许上传的文件扩展类型 
'  up.extension=SQSTRINGMARKER2
'  up.charset=SQSTRINGMARKER3            '必选项, 上传页编码
'  
'  up.interval=30                '必选项, 每次上传间隔  单位: 秒
'  up.gobackSecond=10            '必选项, 上次完毕后返回时间 单位: 秒
'  up.gobackurl=SQSTRINGMARKER4              '必选项, 上次完毕后返回路径, 单位: url
'  
'  up.prefix=""                  '非必选, 上传前缀'
'  up.autorename=false           '非必选, 是否自动重命名
'  up.rndpostfix=false           '非必选, 是否添加随机后缀
'  
'  up.ckeckfile=true             '非必选, 是否检测恶意代码
'  '非必选, 要进行检测恶意代码的文件类型
'  up.listForCheck=SQSTRINGMARKER5 
'  
'  up.autoRenameOpt=true         '非必选, 是否显示表单的自动重命名复选框
'  up.prefixOpt=true             '非必选, 是否显示表单的自定义前缀文件框
'  up.rndPostfixOpt=true         '非必选, 是否显示表单的随机后缀复选框
'  
'  up.header                     '非必选, 程序头部信息
'  
'  if Request.QueryString(SQSTRINGMARKER6)=SQSTRINGMARKER7 then
'   up.exec                       '必选项, 处理上传
'   up.report                     '必选项, 汇报上传后结果
'   'Response.write(up.filelist)  '返回已上传的所有文件路径, 数据类型为字符串, 以逗号分隔'
'  end if
'  
'  up.info                       '非必选, 显示上传限制信息 
'   
'  up.form                       '必选项, 显示上传表单
'  
'  up.about                      '非必选, 显示作者及程序相关信息
'  up.footer                     '非必选, 显示程序底部信息
' set up=nothing
 
 '---------------------------------------------------------------------'
 ' shawl.qiu asp/vbscript 无组件上传类 v1.2
 '---------------------------------------------------------------------'
 '---------------------------------------------------------------------begin class sqUpload
 class sqUpload
   '------------------------------------begin event
   private sub class_initialize()
    auSubject="shawl.qiu asp/vbscript 无组件上传类"
    auVersion="v1.2"
    au="shawl.qiu"
    auEmail="shawl.qiu@gmail.com"
    auBlog="http://blog.csdn.net/btbtd"
    auCreateDate="2007-1-18"
    auPubDate="2007-1-19"
    auUpDesc="本次升级重写了大部分代码, 以更合理更OO的结构重写本程序, 提高了很多效率."&_
    "<br/>修正了 1.0 Final 中的一点小 bug."&_
    "<br/>备注: 1.1 版本没发布, 这大概会是鄙人的一个习惯, 1.1 版本 大多是在捉虫子,"&_
    " 因此鄙人的 1.1 大多数没发布"
    
    'init public variable'
    item=10
    action="?id=ufile"
    totalsize=1024*1024 'kb'
    singlesize=1024 'kb'
    path="/upload/"
    extension="7z,rar,zip,mp3,bmp,gif,jpg,jpeg,png,txt,swf"
    charset="utf-8"
    
    filelist=""
    
    interval=10
    gobackSecond=10
    gobackurl="?"
    
    autoRenameOpt=false
    prefixOpt=false
    rndPostfixOpt=false
    
    tl_totalfield=0
    tl_totalfile=0
    tl_totalnotfile=0
    tl_finalupload=0
    
    prefix=""
    autorename=false
    rndpostfix=false
    ckeckfile=false
    listForCheck=""
    
    tl_bAllowUpload=true
    
    wordAutoRename="自动重命名"
    wordRndPostfix="随机后缀"
    wordPrefix="添加前缀"
    
    wordPrefixValue="prx_"
    wordSubmit="现在上传文件?"
    wordReset="现在重置?"
    
    redim tl_arCkFl(4)
     tl_arCkFl(0)=chrB(60)&chrB(37) '<%
     tl_arCkFl(1)=chrB(37)&chrB(62) '%/>
     tl_arCkFl(2)=chrB(115)&chrB(99)&chrB(114)&chrB(105)&chrB(112)&chrB(116)
     tl_arCkFl(3)=chrB(83)&chrB(99)&chrB(114)&chrB(105)&chrB(112)&chrB(116)
     tl_arCkFl(4)=chrB(83)&chrB(67)&chrB(82)&chrB(73)&chrB(80)&chrB(84)
    
    debug=false
    
    Response.write("<style type=""text/css"">"&vbcrlf)
    Response.write("/* <![CDATA[ */"&vbcrlf)
    Response.write(" .dspBl{ display:block;}"&vbcrlf)
    Response.write(" .report * li{margin:5px 0px}"&vbcrlf)
    Response.write(" .crRed{color:red}"&vbcrlf)
    Response.write(" .crFcs{color:fuchsia}"&vbcrlf)
    Response.write(" .ftBld{font-weight:bold;}"&vbcrlf)
    Response.write(" .crHl{background:yellow; color:black;}"&vbcrlf)
    Response.write(" .au_header { font-weight:bold; text-align: center; "&_
    "color:bold; display:table; width:96%;"&vbcrlf)
    Response.write("  font-size:28px; padding:%2; }"&vbcrlf)
    Response.write(" .au_footer{text-align: center; display:table; width:98%; padding:%1; }"&_
    vbcrlf)
    Response.write(" hr{"&vbcrlf)
    Response.write("  border-top: 1px dashed #FFFFFF!important;"&vbcrlf)
    Response.write("  border-right: 1px dashed #FFFFFF!important;"&vbcrlf)
    Response.write("  border-bottom:1px dashed black!important; "&vbcrlf)
    Response.write("  border-left: 1px dashed #FFFFFF!important;"&vbcrlf)
    Response.write("  margin:10px 0px;"&vbcrlf)
    Response.write("  }"&vbcrlf)
    Response.write("/* ]]> */"&vbcrlf)
    Response.write("</style>")
   end sub 'class_initialize'
   
   private sub class_terminate()
   
   end sub 'class_terminate'
   '------------------------------------end event
   '------------------------------------begin public variable
   '---------------begin about
   public auSubject, auVersion, au, auEmail, auBlog, auCreateDate, auPubDate, auUpDesc
   '---------------end about
   public item
   public action 
   public totalsize
   public singlesize
   public path
   public extension
   public charset
   
   public filelist
   
   public interval
   public gobackSecond
   public gobackurl
   
   public autoRenameOpt
   public prefixOpt
   public rndPostfixOpt
   
   public prefix
   public autorename
   public rndpostfix
   public ckeckfile
   public listForCheck
   
   public wordAutoRename
   public wordRndPostfix
   public wordPrefix
   public wordSubmit
   public wordReset
   public wordPrefixValue
     
   public debug
   '------------------------------------end public variable
   
   '------------------------------------begin public method
   public property get form
    form=fForm
   end property
   
   public property get exec
    exec=fExec
   end property
   
   public property get info
    info=fInfo
   end property
   
   public property get report
    report=fReport
   end property
   
   public property get header
    header=fHeader
   end property
   
   public property get footer
    footer=fFooter
   end property
   
   public property get about
    about=fAbout
   end property
   '------------------------------------end public method
   
   '------------------------------------begin private variable
   private tl_totalbytes
   private tl_sizebykb
   private tl_phspath
   private tl_bAllowUpload
   
   private tl_totalHeader
   private tl_totalfield
   private tl_totalfile
   private tl_totalnotfile
   private tl_finalupload
   
   private tl_arCkFl
   
   private tl_arErrNoExt
   private tl_arErrNotAllowExt
   private tl_arErrMaliceCode
   private tl_arErrFileExists
   private tl_arErrOversize
   private tl_arErrOversizeDetail
   
   private tl_arUploadList
   private tl_arUploadDetail
   private tl_arFinalName
   
   '------------------------------------end private variable
   
   '------------------------------------begin private method
   private function fExec()
    dim dtInterval
    if session("timestamp")="" then session("timestamp")=now()
     dtInterval=dateDiff("s",now(),session("timestamp"))
     
    if  dtInterval>0  then
     call suErr1("每次上传的时间间隔为""秒后才能继续上传, 请稍候...,","秒""?",_
      dtInterval, interval)
     tl_bAllowUpload=false
     exit function
    else
     session("timestamp")=dateAdd("s",interval,now())
    end if
    
    tl_totalbytes=Request.TotalBytes
    
    '-----------------------------------检测是否有数据在上传'
    if tl_totalbytes=0 then 
     call suErr("上传数据为空, 上传处理被中止,""?"3)
     Response.End()
    end if
    
    tl_sizebykb=tl_totalbytes/1024
    
    '-----------------------------------检测上传总大小是否超出限制'
    if totalsize<tl_sizebykb then 
     dim sUpsize:
     sUpsize="上传总大小为: "&formatNumber(tl_sizebykb)&" Kb, 超过总大小限制: "&_
     totalsize&" kb, 约合 "&(totalsize/1024)&" mb, "
     'Response.write(sUpsize)
     call suErr( sUpsize, "?"3)
     Response.End()
    end if
    
    '-----------------------------------检测上传路径是否存在
    if fFsoCkFdr(path, true)=false then 
     call suErr("指定的上传文件路径不存在""?"3)
     Response.End()
    end if 
    
    tl_phspath=Server.MapPath(path)
    
    dim bnTotal:bnTotal=Request.BinaryRead(tl_totalbytes)
    dim bnMarker:bnMarker=leftB(bnTotal,instrB(bnTotal,chrB(32))-1) ' 文件头状况分隔符'
    dim bnLf:bnLf=chrB(13)&chrB(10) 
    dim bnFieldMarker:bnFieldMarker=leftB(bnTotal,inStrB(bnTotal,chrB(13))-1)
    
    dim iStart:iStart=1
    dim iJump
    dim iBnStart, iBnEnd
    
    dim arHeaderStartTemp, arHeaderEndTemp, arHeaderStrTemp
    dim arHeaderStart, arHeaderEnd, arHeaderStr
    dim arFieldStart, arFieldEnd
    
    do
     iJump=inStrB(iStart, bnTotal, bnMarker)
     if iJump<>0 then
      iStart=iJump+1 '取二进制开始位置'
      iBnStart=inStrB(iStart, bnTotal, bnLf&bnLf) '取二进制结束位置
      iBnEnd=inStrB(iBnStart+5, bnTotal, bnFieldMarker)
      tl_totalHeader=tl_totalHeader+1 ' 取头部总数

      if inStrB(midB(bnTotal, iBnStart+436),midB(bnFieldMarker,1))=0 then
      
       '-----------------------------临时 取头部起始位置'
       if isArray(arHeaderStartTemp) then redim preserve arHeaderStartTemp(tl_totalfield) _
       else redim arHeaderStartTemp(tl_totalfield)
        arHeaderStartTemp(tl_totalfield)=iStart-1
        
       '-----------------------------临时 取头部结束位置'
       if isArray(arHeaderEndTemp) then redim preserve arHeaderEndTemp(tl_totalfield) else _
       redim arHeaderEndTemp(tl_totalfield)
        arHeaderEndTemp(tl_totalfield)=iBnStart+2-iStart
        
       '-----------------------------临时 取头部字串'
       if isArray(arHeaderStrTemp) then redim preserve arHeaderStrTemp(tl_totalfield) _
       else redim arHeaderStrTemp(tl_totalfield)
        arHeaderStrTemp(tl_totalfield)=_
         fBin2Str(midB(bnTotal,iStart-1,arHeaderEndTemp(tl_totalfield)),charset)

       
       '-----------------------------检测附加选项'
       if inStr(arHeaderStrTemp(tl_totalfield),"filename")=0 and inStr(_
        arHeaderStrTemp(tl_totalfield),"; name=")<>0 then
        select case fRe(arHeaderStrTemp(tl_totalfield),true,true,_
        true,"[/s/S]*?name/=/""(.*?)""[/s/S]*","$1")
         case "nprefix"
           prefix=fBin2Str(midB(bnTotal,iBnStart,iBnEnd-iBnStart),charset)
           if debug then
            Response.write("<br/>prefix string: "&prefix)
           end if
         case "nrndpfx": rndpostfix=true
         case "nautorename": autorename=true
        end select
        
        if debug then
          Response.write("<br/>header not upload file: "&arHeaderStrTemp(tl_totalfield))
        end if
        tl_totalnotfile=tl_totalnotfile+1
       else
        if inStr(arHeaderStrTemp(tl_totalfield)"filename=""""")=0 then 
        
         '-----------------------------取头部起始位置'
         if isArray(arHeaderStart) then redim preserve arHeaderStart(tl_totalfile) _
         else redim arHeaderStart(tl_totalfile)
          arHeaderStart(tl_totalfile)=iStart-1
          
         '-----------------------------取头部结束位置'
         if isArray(arHeaderEnd) then redim preserve arHeaderEnd(tl_totalfile) else _
         redim arHeaderEnd(tl_totalfile)
          arHeaderEnd(tl_totalfile)=iBnStart+2-iStart
          
         '-----------------------------取头部字串'
         if isArray(arHeaderStr) then redim preserve arHeaderStr(tl_totalfile) else redim _
          arHeaderStr(tl_totalfile)
          arHeaderStr(tl_totalfile)=_
           fBin2Str(midB(bnTotal,iStart-1,arHeaderEnd(tl_totalfile)),charset)
        
        
         '-----------------------------取文件内容起始位置'
         if isArray(arFieldStart) then redim preserve arFieldStart(tl_totalfile) else redim  _
          arFieldStart(tl_totalfile)
         arFieldStart(tl_totalfile)=iBnStart
        
         '-----------------------------取文件内容结束位置'
         if isArray(arFieldEnd) then redim preserve arFieldEnd(tl_totalfile) else redim _
          arFieldEnd(tl_totalfile)
         arFieldEnd(tl_totalfile)=iBnEnd
        
         if debug then 
          Response.write("<br/>header "&tl_totalfile&" start position: "&_
           arHeaderStartTemp(tl_totalfile))
           
          Response.write("<br/>header "&tl_totalfile&" end read plus: "&_
           arHeaderEndTemp(tl_totalfile))
           
          Response.write("<br/>header "&tl_totalfile&" string: "&_
           arHeaderStrTemp(tl_totalfile))
           
          Response.write("<br/>file content "&tl_totalfile&" start position: "&_
           arFieldStart(tl_totalfile))
           
          Response.write("<br/>file content "&tl_totalfile&" end position: "&_
           arFieldEnd(tl_totalfile))
           
          Response.write("<br/>")
         end if
         
         tl_totalfile=tl_totalfile+1
        end if
       end if
        
       tl_totalfield=tl_totalfield+1 ' 取上传总文件数
      end if
     
     else
      exit do
     end if
    loop 
    
    if debug then 
     Response.write("<br/>上传头部总数: "&tl_totalHeader)
     Response.write("<br/>可用头部总数: "&(tl_totalfile+tl_totalnotfile))
     Response.write("<br/>上传文件总数: "&tl_totalfile)
     Response.write("<br/>上传非文件总数: "&tl_totalnotfile)
     
     Response.write("<br/>文件前缀: "&prefix)
     Response.write("<br/>自动重命名: "&autorename)
     Response.write("<br/>随机后缀: "&rndpostfix)
     
     Response.write("<p/>上传虚拟路径: "&path)
     Response.write("<br/>上传物理路径: "&tl_phspath)
     Response.write("<br/>上传总大小为: "&formatNumber(tl_sizebykb)&" Kb")
     Response.write("<br/>限制总大小为: "&(totalsize)&" Kb")
     Response.write("<br/>限制每文件大小为: "&(singlesize)&" Kb")
    end if
    
    '-----------------------------------检测是否有文件上传'
    if not isArray(arHeaderStr) then 
     call suErr("没有可上传的文件,""?"3)
     Response.End()
    end if
    
    '-----------------------------------开始处理上传文件'
    dim iSave
    dim sFlNm, sFlPrx, sFlPox, sFnlNm
    dim sFlpoxTemp
    dim bnFileContent
    dim sPathTemp
    dim iArCkTemp
    dim bFlag, bFileExist
    dim sAutorename, iAutorename
    dim iUpsizeByteTemp, iUpsizeKbTemp, iUpsizeMbTemp
    dim sUPDetailTemp
    
    for iSave=0 to uBound(arHeaderStr)
     iAutorename=1
     bFlag=true
     bFileExist=false
     sFlNm=fRe(arHeaderStr(iSave)falsetruefalse,_
      "[/s/S]*filename=""(.*?)""[/s/S]*""$1")
      
      sFlNm=fRe(sFlNm, falsetruefalse,".*//(.*)""$1")
     if inStr(sFlNm, ".")<>0 then 
      sFlPrx=fRe(sFlNm, falsetruefalse,"(.*)/..*""$1")
      sFlPox=fRe(sFlNm, falsetruefalse,".*/.(.*)""$1")
      
      '-------------------------------------允许上传的文件扩展名'
      if fReTest(extension, "/b"&sFlPox&"/b") then
       sFlPrx=fRe(prefix&sFlPrx, truetruefalse,"/s+", "")
       if rndpostfix then
        sFlpoxTemp=fRndStr(10)
        sFlPrx=sFlPrx&sFlpoxTemp  
       end if
       sFnlNm=sFlPrx&"."&sFlPox
       bnFileContent=_
        midB(bnTotal,arFieldStart(iSave)+3,arFieldEnd(iSave)-arFieldStart(iSave)-3)
        sPathTemp=path+sFnlNm
       
       if ckeckfile then 
        if fReTest(listForCheck, "/b"&sFlPox&"/b") then
         for iArCkTemp=0 to uBound(tl_arCkFl)
          '--------------------------------检测恶意代码
          if inStrB(1, bnFileContent, tl_arCkFl(iArCkTemp)1)<>0 then 
           if isArray(tl_arErrMaliceCode) then redim preserve _
            tl_arErrMaliceCode(uBound(tl_arErrMaliceCode)+1) else redim tl_arErrMaliceCode(0)
            tl_arErrMaliceCode(uBound(tl_arErrMaliceCode))=sFlNm
            bFlag=false
           exit for
          end if
         next 
        end if
       end if
       
       if bFlag then
        bFileExist=fCheckFile(Server.MapPath(sPathTemp))
        
        iUpsizeByteTemp=arFieldEnd(iSave)-arFieldStart(iSave)-3
        iUpsizeKbTemp=iUpsizeByteTemp/1024
        iUpsizeMbTemp=iUpsizeKbTemp/1024
      
        if bFileExist then '存在相同名称的文件'
         if debug then Response.write("<br/>已存在文件: "&sPathTemp)
         
         if autorename then
          do 
           sAutorename=fRe(sPathTemp, falsetruefalse,"(.*)/..*""$1")
           sAutorename=sAutorename&"_"&iAutorename&"."&sFlPox
           if fCheckFile(Server.MapPath(sAutorename))=false then
            exit do
           end if
           iAutorename=iAutorename+1
          loop
          
          sFnlNm=fRe(sAutorename, falsetruefalse,".*//(.*)""$1")
           
          '------------------------------------------保存上传文件子过程'
          call suSavingFile(iUpsizeKbTemp, singlesize, sAutorename, sFlNm, sFnlNm, _
          iUpsizeByteTemp, iUpsizeMbTemp, bnTotal, iSave, arFieldStart, arFieldEnd)
          
          if debug then Response.write("<br/>自动重命名: "&sAutorename)
         else 
          if isArray(tl_arErrFileExists) then redim preserve _
           tl_arErrFileExists(uBound(tl_arErrFileExists)+1) else redim tl_arErrFileExists(0)
           tl_arErrFileExists(uBound(tl_arErrFileExists))=sFnlNm
           if debug then Response.write("<br/> 已存在相同的文件: "&sFnlNm)
         end if
         
        else 
          
          if debug then
           Response.write("<br/>")
           Response.write("<br/> 上传文件大小大于单文件限制:"&(iUpsizeKbTemp>singlesize))
           Response.write("<br/>文件大小:"&iUpsizeByteTemp&" byte, 约合: "&_
           (formatNumber(iUpsizeKbTemp))&" kb")
          end if
          
          '------------------------------------------保存上传文件子过程'
          call suSavingFile(iUpsizeKbTemp, singlesize, sPathTemp, sFlNm, sFnlNm, _
          iUpsizeByteTemp, iUpsizeMbTemp, bnTotal, iSave, arFieldStart, arFieldEnd)
          
        end if
       end if
       
      else 
       '------------------------------------不允许上传的文件扩展名'
       if isArray(tl_arErrNotAllowExt) then redim preserve _
        tl_arErrNotAllowExt(uBound(tl_arErrNotAllowExt)+1) else redim tl_arErrNotAllowExt(0)
        tl_arErrNotAllowExt(uBound(tl_arErrNotAllowExt))=sFlNm
        
       if debug then
        Response.write("<br/>")
        Response.write("<br/>不允许上传的文件扩展名: "&sFlNm)
       end if
      end if
      
      if debug then
       Response.write("<br/>文件名: "&sFlNm)
       Response.write("<br/>前缀: "&prefix)
       Response.write("<br/>后缀: "&sFlpoxTemp)
       Response.write("<br/>最终文件名: "&sFnlNm)
      end if
     else
      '--------------------------------------没有扩展名的文件
      if isArray(tl_arErrNoExt) then redim preserve tl_arErrNoExt(uBound(tl_arErrNoExt)+1) _
      else redim tl_arErrNoExt(0)
      tl_arErrNoExt(uBound(tl_arErrNoExt))=sFlNm
     end if
    next 
   end function 'fExec'
   
   private sub suSavingFile(iUpsizeKbTemp, singlesize, sPathTemp, sFlNm, sFnlNm, _
   iUpsizeByteTemp, iUpsizeMbTemp, bnTotal, iSave, arFieldStart, arFieldEnd)
    '----------------------------------判断单文件是否超出限制大小'
    if iUpsizeKbTemp<=singlesize then 
     call fBinSv2fl(bnTotal,arFieldStart(iSave)+3,arFieldEnd(iSave)-_
     arFieldStart(iSave)-3, sPathTemp, 2)
     
     if isArray(tl_arUploadList) then redim preserve _
      tl_arUploadList(uBound(tl_arUploadList)+1) else redim tl_arUploadList(0)
      tl_arUploadList(uBound(tl_arUploadList))=sFlNm
     
     if isArray(tl_arFinalName) then redim preserve _
      tl_arFinalName(uBound(tl_arFinalName)+1) else redim tl_arFinalName(0)
      tl_arFinalName(uBound(tl_arFinalName))=sFnlNm
     
     if isArray(tl_arUploadDetail) then redim preserve _
      tl_arUploadDetail(uBound(tl_arUploadDetail)+1) else redim tl_arUploadDetail(0)
      tl_arUploadDetail(uBound(tl_arUploadDetail))=_
      "上传文件大小为: "&iUpsizeByteTemp&" Byte, 约合 "&formatNumber(iUpsizeKbTemp)&_
      " Kb, "&formatNumber(iUpsizeMbTemp)&" Mb"
      'iUpsizeKbTemp'
     tl_finalupload=tl_finalupload+1
    else 
     
     if isArray(tl_arErrOversize) then redim preserve _
      tl_arErrOversize(uBound(tl_arErrOversize)+1) else redim tl_arErrOversize(0)
      tl_arErrOversize(uBound(tl_arErrOversize))=sFlNm
      
     if isArray(tl_arErrOversizeDetail) then redim preserve _
      tl_arErrOversizeDetail(uBound(tl_arErrOversizeDetail)+1) else redim _
      tl_arErrOversizeDetail(0)
      tl_arErrOversizeDetail(uBound(tl_arErrOversizeDetail))="上传文件: "&sFlNm&_
      ", 总大小约为 "&formatNumber(iUpsizeKbTemp)&" kb, 超出单文件限制大小 "&_
      singlesize&" kb, 已被中止上传."
      
    end if
   end sub 'suSavingFile'
   
   private function fFileList(aFileList)
    dim sTemp, aTemp, iUbound, iTemp
    if isArray(aFileList) then
     iUbound=ubound(aFileList)
     redim aTemp(iUbound)
     for iTemp=0 to iUbound
      aTemp(itemp)=path&aFileList(iTemp)
     next
     sTemp=join(aTemp,",")
    else
     sTemp=""
    end if
    filelist=sTemp
   end function 'fFileList'
   
   private function fReport()
    
    if not tl_bAllowUpload then
     exit function
    end if
    
    call suErr1("上传操作处理完毕""返回""秒后返回""?", gobackSecond, gobackSecond)
    
    if isArray(tl_arErrNoExt) or isArray(tl_arErrNotAllowExt) or isArray(tl_arErrMaliceCode) _
     or isArray(tl_arErrFileExists) or isArray(tl_arUploadList) or isArray(tl_arErrOversize) _
     then
     
     Response.write("<div class='report'>")
     Response.write("<h2>上传信息</h2>")
     
     Response.write("<h3 class='crRed'>本次上传文件总数: "& tl_totalfile&", 成功上传文件总数: "&_
     tl_finalupload&", 被终止上传文件总数: "&(tl_totalfile-tl_finalupload)&".</h3>")
     
     
     Response.write("<h2>上传明细:</h2>")
     
     '---------------------------------已上传文件
     if isArray(tl_arUploadList) then
      dim iUplist
      Response.write("<ol>")
      Response.write("<label class='crHl dspBl'>已上传文件:</label>")
      for iUplist=0 to uBound(tl_arUploadList)
       Response.write("<li><b>")
       Response.write(tl_arUploadList(iUplist))
       Response.write("</b><label class='dspBl'>上传描述:<br/>最终文件名: <b class='crFcs'>"&_
       tl_arFinalName(iUplist)&"</b><br/>"&tl_arUploadDetail(iUplist)&"</label>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
      
      fFileList(tl_arFinalName) 
     end if
     
     '---------------------------------超出单文件大小限制
     if isArray(tl_arErrOversize) then
      dim iOversize
      Response.write("<ol>")
      Response.write("<label>超出单文件大小限制的文件有 "&(uBound(tl_arErrOversize)+1)&_
      " 个.</label>")
      for iOversize=0 to uBound(tl_arErrOversize)
       Response.write("<li><b class='crRed'>")
       Response.write(tl_arErrOversize(iOversize))
       Response.write("</b><label class='dspBl'>被中止上传描述:<br/>"&_
       tl_arErrOversizeDetail(iOversize)&"</label>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
     end if 
     
     '---------------------------------已存在相同的文件名
     if isArray(tl_arErrFileExists) then
      dim iAlreadyExists
      Response.write("<ol>")
      Response.write("<label>已存在相同的文件名, "&(uBound(tl_arErrFileExists)+1) &_
      " 个文件无法上传.</label>")
      for iAlreadyExists=0 to uBound(tl_arErrFileExists)
       Response.write("<li><b class='crRed'>")
       Response.write(tl_arErrFileExists(iAlreadyExists))
       Response.write("</b>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
     end if
     
     '---------------------------------不允许上传的文件扩展类型
     if isArray(tl_arErrNotAllowExt) then
      dim iNotAllowExt
      Response.write("<ol>")
      Response.write("<label>不允许上传的文件扩展类型, "&(uBound(tl_arErrNotAllowExt)+1) &_
      " 个文件无法上传.</label>")
      for iNotAllowExt=0 to uBound(tl_arErrNotAllowExt)
       Response.write("<li><b class='crRed'>")
       Response.write(tl_arErrNotAllowExt(iNotAllowExt))
       Response.write("</b>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
     end if
     
     '---------------------------------检测到包含恶意代码的文件
     if isArray(tl_arErrMaliceCode) then
      dim iMaliceCode
      Response.write("<ol>")
      Response.write("<label>检测到包含恶意代码的文件, "&(uBound(tl_arErrMaliceCode)+1) &_
      " 个文件无法上传.</label>")
      for iMaliceCode=0 to uBound(tl_arErrMaliceCode)
       Response.write("<li><b class='crRed'>")
       Response.write(tl_arErrMaliceCode(iMaliceCode))
       Response.write("</b>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
     end if
     
     '---------------------------------检测到包含恶意代码的文件
     if isArray(tl_arErrNoExt) then
      dim iNoExt
      Response.write("<ol>")
      Response.write("<label>没有扩展名的文件, "&(uBound(tl_arErrNoExt)+1) &_
      " 个文件无法上传.</label>")
      for iNoExt=0 to uBound(tl_arErrNoExt)
       Response.write("<li><b class='crRed'>")
       Response.write(tl_arErrNoExt(iNoExt))
       Response.write("</b>")
       Response.write("</li>")
      next
      Response.write("</ol>")
      Response.write("<hr/>")
     end if
     
     Response.write("</div>")

    else 
     exit function
    end if
   end function 'fReport()'
   
   private function fBinSv2fl(bin, bStart, bEnd, filepath_, ovWrite)
   '--------------------------------------
   ' 截取二进制流保存为文件 By shawl.qiu
   http://blog.csdn.net/btbtd
   '---------------------------
   ' sample call: call fBinSv2fl(bRead,fieldStartPsti(i)+3,fieldEndPsti(i)-fieldStartPsti(i)-3, fileName, 2)
   '------------
   ' 参数说明:
   '---------
   ' bin: 源二进制流
   ' bStart: 截取二进制流的起始位置
   ' bEnd: 截取二进制流的结束位置
   ' filepath_: 保存文件的路径
   ' ovWrite: 是否覆盖原有文件. 1: 不覆盖; 2. 覆盖
   '--------------------------------------
     filepath_=server.MapPath(filepath_)
    dim stm_, fromStm_ 
    set stm_=createObject("adodb.stream")
     stm_.type=1 
     stm_.mode=3 
     stm_.open
     stm_.write bin 
     set fromStm_=createOBject("adodb.stream")
      with fromStm_
       .type=1
       .mode=3
       .open
       stm_.position = bStart 
       stm_.copyTo fromStm_, bEnd 
       .saveTofile filepath_, ovWrite
       .close
      end with
     set fromStm_=nothing
     stm_.close  'shawl.qiu code'
    set stm_=nothing
   end function
  
   private sub suErr(byval sStr, byval sCurl, byval iSecond)
    dim sUrl:sUrl=Request.ServerVariables("HTTP_REFERER")
    if sUrl="" then sUrl="/"
    if sCurl<>"" then sUrl=sCurl
    Response.write("<meta http-equiv='refresh' content='"&iSecond&";URL="&gobackurl&"'>")
    Response.write("<div style='display:table;width:100%;background-color:yellow!important;"&_
    "color:black!important;text-align:center!important;'>"&sStr&" "&iSecond&" 秒后返回.</div>")
   end sub 'suErr'
  
   private sub suErr1(byval sStr, byval sGbPox, byval sGbMid, byval sCurl,_
    byval iSecond, byval iDesc)
    dim sUrl:sUrl=Request.ServerVariables("HTTP_REFERER")
    if sUrl="" then sUrl="/"
    if sCurl<>"" then sUrl=sCurl
     Response.write("<script type='text/javascript'>"&vbcrlf)
     Response.write("//<![CDATA["&vbcrlf)
     Response.write(" onload=function(){"&vbcrlf)
     Response.write("  fTimer("&iSecond&",'timer', 10);"&vbcrlf)
     Response.write(" }"&vbcrlf)
     Response.write("  function fTimer(iTimestamp, sId, iMs){"&vbcrlf)
     Response.write("  if(!(iTimestamp.constructor==Date)){"&vbcrlf)
     Response.write("   var sqTimeStamp=new Date();"&vbcrlf)
     Response.write("   sqTimeStamp.setSeconds(sqTimeStamp.getSeconds()+iTimestamp);"&vbcrlf)
     Response.write("   iTimestamp=sqTimeStamp;"&vbcrlf)
     Response.write("  }"&vbcrlf)
     Response.write("    var tl=arguments.callee;"&vbcrlf)
     Response.write("    if(typeof sId=='string'){"&vbcrlf)
     Response.write("   var oEle=document.getElementById(sId);"&vbcrlf)
     Response.write("  } else {"&vbcrlf)
     Response.write("   var oEle=sId;"&vbcrlf)
     Response.write("  }"&vbcrlf)
     Response.write("  var dt=new Date();"&vbcrlf)
     Response.write("  var iCk=((iTimestamp.getTime()-dt.getTime())/1000).toFixed(3);"&vbcrlf)
     Response.write("  if(iCk<=0){"&vbcrlf)
     Response.write("   oEle.innerHTML='00.000';"&vbcrlf)
     Response.write("   return false;"&vbcrlf)
     Response.write("  } else {"&vbcrlf)
     Response.write("   oEle.innerHTML=iCk;"&vbcrlf)
     Response.write("   var iTimer=setTimeout(function(){tl(iTimestamp, oEle, iMs)},iMs); "&_
     vbcrlf)
     Response.write("  }"&vbcrlf)
     Response.write(" } // end function fTimer // shawl.qiu script"&vbcrlf)
     Response.write("//]]>"&vbcrlf)
     Response.write("</script>"&vbcrlf)
     Response.write("<meta http-equiv='refresh' content='"&iSecond&";URL="&gobackurl&"'>")
     Response.write("<div style='display:table;width:100%;background-color:yellow!important;"&_
     "color:black!important;text-align:center!important;'>"&sStr&" "&iDesc&_
     " "&sGbMid&", 还有<span id='timer'>"&iSecond&"</span> "&sGbPox&"</div>")
   end sub 'suErr1'
   
   private function fForm()
    Response.write("<form action='"&action&"' method='post' id='uform'"&_
    " enctype='multipart/form-data' >"&vblf)
    dim i
    for i=1 to item
     Response.write("<div class='itemlist'>")
     Response.write("<input type='file' name='file' class='upButton' />")
     Response.write("</div>"&vblf)
    next 
    if autoRenameOpt=true then 
     Response.write("<div class='btnOpt'>")
     Response.write(" "&wordAutoRename&": <input type='checkbox' name='nautorename'"&_
     " checked='checked' />")
     Response.write("</div>")
    end if
    if rndPostfixOpt=true then 
     Response.write("<div class='btnOpt'>")
     Response.write(" "&wordRndPostfix&": <input type='checkbox' name='nrndpfx'"&_
     " checked='checked' />")
     Response.write("</div>")
    end if
    if prefixOpt=true then 
     Response.write("<div class='btnOpt'>")
     Response.write(" "&wordPrefix&": <input type='text' name='nprefix' value='"&_
      wordPrefixValue&"' size='15'/>")
     Response.write("</div>")
    end if
    Response.write("<div class='btnAct'><input type='submit' onclick="""&_
     "return confirm('"&wordSubmit&"?')""/> ")
    Response.write("<input type='reset'  onclick="""&_
     "return confirm('"&wordReset&"')""/> </div> ")
    Response.write("</form>")
    if debug then  Response.write("<a href='?'>back</a>")  
   end function 'fForm'
   
   private function fInfo()
    Response.write("<div class='upInfo' style='padding:5px 0px'>")

    Response.write("<div>")
    Response.write("<b>允许上传的文件类型</b>: "&extension)
    Response.write("</div>")
    Response.write("<div>")
    Response.write("<b>上传总大小限制</b>: "&totalsize&" kb")
    Response.write(", <b>每文件总大小限制</b>: "&singlesize&" kb.")
    Response.write("</div>")
    Response.write("<div>")
    Response.write("<b>每次上传时间间隔为</b>: "&interval&" 秒")
    Response.write("</div>")

    Response.write("</div>")
   end function 'fInfo'
   
   private function fHeader()
    'public auSubject, auVersion, au, auEmail, auBlog, auCreateDate'
    Response.write("<div class='au_header'>")
    Response.write(auSubject&" "&auVersion)
    Response.write("</div>")
   end function 'fHeader'
   
   private function fFooter()
    'public auSubject, auVersion, au, auEmail, auBlog, auCreateDate'
    Response.write("<div class='au_footer'>")
    Response.write("版权声明: 本程序允许非商业性的自由传播与应用, 商业使用者需经作者许可,"&_
    " 否则将追究法律责任.")
    Response.write("</div>")
   end function 'fHeader'
   
   private function fAbout()
    Response.write("<div class='about'>")
    
    Response.write("<ul>")
    Response.write("<li class='ftBld'>subject: "&auSubject&"</li>")
    Response.write("<li>version: "&auVersion&"</li>")
    Response.write("<li>author: "&au&"</li>")
    Response.write("<li>e-mail: "&auEmail&"</li>")
    Response.write("<li>blog: "&auBlog&"</li>")
    Response.write("<li>created: "&auCreateDate&"</li>")
    Response.write("<li>published: "&auPubDate&"</li>")
    Response.write("</ul>")
    
    Response.write("<ol>")
    Response.write("<label class='ftBld'>功能摘要:</label>")
    Response.write("<li>支持 自定义上传多个文件</li>")
    Response.write("<li>支持 中文文件名</li>")
    Response.write("<li>支持 自定义上传总大小</li>")
    Response.write("<li>支持 自定义上传每文件总大小</li>")
    Response.write("<li>支持 自定义上传文件类型</li>")
    Response.write("<li>支持 自定义上传间隔</li>")
    Response.write("<li>支持 自定义是否重命名文件(在已存在相同名称的文件名时)</li>")
    Response.write("<li>支持 自定义是否添加随机后缘</li>")
    Response.write("<li>支持 自定义添加前缀</li>")
    Response.write("</ol>")
    
    Response.write("<ul>")
    Response.write("<label class='ftBld'>升级描述:</label>")
    Response.write("<li>"&auUpDesc&"</li>")
    Response.write("</ul>")
    
    Response.write("</div>")
   end function 'fAbout'
   
   private function fFsoCkFdr(byval sPath, byval bCov)
   ' FSO 检测文件夹函数 By shawl.qiu
    if bCov then sPath=Server.MapPath(sPath)
    fFsoCkFdr=createObject("scripting.fileSystemObject").folderExists(sPath)
   end function 'fFsoCkFdr'
   
   private function fBin2Str(str, charSet)
   '--------------------------------------
   ' 二进制转字符串函数 By shawl.qiu
   http://blog.csdn.net/btbtd
   '--------------------------
   ' 参数说明:
   '----------
   ' str: 要转换成字符串的二进制数据
   ' charSet: 字符串默认编码集, 如不指定, 则默认为 gb2312
   '-------------
   ' sample call: response.write fBin2Str(midB(fStr2Bin(str, SQSTRINGMARKER354),1),SQSTRINGMARKER355)
   '--------------------------------------
   ' 注意: 二进制字符串必须先用 midB(binaryString,1) 读取(可自定读取长度).
   '--------------------------------------
    dim stm_ 
    set stm_=createObject("adodb.stream")
     with stm_
      .type=2 
      .open
      .writeText str
      .Position = 0
      if charSet<>"" then
       .CharSet = charSet
      else 
       .CharSet = "gb2312"
      end if
       fBin2Str=.ReadText
      .close
     end with 'shawl.qiu code'
    set stm_=nothing
   end function 'fBin2Str'
   
   private function fRe(str,glb,igc,mtl,pt,rpt)
    dim re
    set re=new RegExp
     re.global=glb
     re.ignoreCase=igc
     re.multiline=mtl
     
     re.pattern=pt
     fRe=re.replace(str,rpt)
    set re=nothing
   end function 'fRe shawl.qiu code'
   
   private function fRndStr(num)
    if isNumeric(num)=false then exit function else num=int(num)
    dim i, j
    dim rndStr(61)
    
    for j=0 to 9:rndStr(j)=cStr(j):next 
    j=10:for i=65 to 90:rndStr(j)=chr(i):j=j+1:next
    j=36:for i=97 to 122:rndStr(j)=chr(i):j=j+1:next
    
    j=0:randomize
    do until j=num:fRndStr=fRndStr+rndStr(Int((61 - 0 + 1) * Rnd + 0)):j=j+1:loop
    erase rndStr
   end function 'shawl.qiu code
   
   private function fReTest(sStr,sPt)
    dim re
    set re=new RegExp
     re.ignoreCase=true
     re.pattern=sPt
     fReTest=re.test(sStr)
    set re=nothing
   end function 'fReTest shawl.qiu code'
   
   private function fCheckFile(path)
   ' FSO 检测文件函数 By shawl.qiu
    fCheckFile=createObject("scripting.fileSystemObject").fileExists(path)
   end function
   '------------------------------------end private method
 end class
 '---------------------------------------------------------------------end class sqUpload
 
 function sqUploadVbs()
  set sqUploadVbs = new sqUpload
 end function
%>


0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场