数据读取中...
 您当前位置:惠州维修 -> 网络-> asp技术交流 文章搜索:  
ASP无组件上传·从原理剖析到实践六
作者:转载 来源:惠州维修
日期: 2004-10-6
放大字体显示 缩小字体显示 打印文章 推荐给朋友
’只写的TotalMaxFileSize属性,填入允许上传文件的总大小 
 Public Property Let TotalMaxFileSize(tmfs) 
   m_lTotalMaxFileSize = tmfs 
 End Property  

 Public Property Get Form(index) 
   Dim Items 
   If isNumeric(index) Then ’是数字?用数字来检索 
     If index > m_dicForms.Count-1 Then 
       err.raise 21,"IndexOutOfBound", "文本元素索引越界" 
     End If 
     Items = m_dicForms.Items 
     Set Form = Items(index) 
   ElseIf VarType(index) = 8 Then ’字符串?也行! 
     If m_dicForms.Exists(index) Then ’存在,就返回值 
       Set Form = m_dicForms.Item(index) 
     Else ’不存在,就给个空值——request对象就是这么做的。 
       Exit Property 
     End If 
   Else ’给了一个不是数字也不是字符串的东东?出错! 
     err.raise 22,"IllegalArgument", "非法的文本元素索引" 
   End If 
 End Property 

 Public Property Get File(index) 
   Dim Items 
   If isNumeric(index) Then ’是数字?用数字来检索 
     If index > m_dicFiles.Count-1 Then 
       err.raise 23,"IndexOutOfBound", "文件元素索引越界" 
     End If 
     Items = m_dicFiles.Items 
     Set File = Items(index) 
   ElseIf VarType(index) = 8 Then ’字符串?也行! 
     If m_dicFiles.Exists(index) Then ’存在,就返回值 
       Set File = m_dicFiles.Item(index) 
     Else ’不存在,出错! 
       err.raise 24,"NullRef", "文件元素索引不存在" 
     End If 
   Else ’给了一个不是数字也不是字符串的东东?出错! 
     err.raise 25,"IllegalArgument", "非法的表单元素索引" 
   End If 
 End Property 

 Private Sub fill 
   ’ 得到数据 
   m_bRawData=request.binaryread(request.totalbytes) 
   ’ 调用这个函数实现递归循环,读取文本/文件单元 
   Call fillEveryFirstPart(m_bRawData) 
 End Sub 

 Private Sub fillEveryFirstPart(data) 
   Dim const_nameis, const_filenameis, bncrlf, divider, startpos, endpos 
   Dim part1, firstline 
   Dim fldname, fldvalue, fElement, filepath, contenttype, ext, afl, dfl 
   Dim isTypeError, i 

   ’ 这就是name=" 
   const_nameis=chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) 
   ’ 这就是filename=" 
   const_filenameis=chrb(102)&chrb(105)&chrb(108)&chrb(101)&_ 
                chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) 
   ’ 这是回车<return> 
   bncrlf=chrb(13) & chrb(10) 
   ’ 得到divider,分隔符 
   divider=leftb(data,instrb(data,bncrlf)-1) 
   ’ 起始位置 
   startpos = instrb(data,divider)+lenb(divider)+lenb(bncrlf) 
   ’ 终止位置,从起始位置开始到下一个divider 
   endpos = instrb(startpos, data, divider)-lenb(bncrlf) 
   If endpos < 1 Then ’没有下一个了!结束! 
     Exit Sub 
   End If 
   part1 = midb(data, startpos, endpos-startpos) 
   ’ 得到part1的第一行 
   firstline = midb(part1, 1, instrb(part1, bncrlf)-1) 

   ’没有filename=",有name=",说明是一个文本单元 
   ’(这里有一个BUG,自己研究一下?当作业吧) 
   If Not instrb(firstline, const_filenameis) > 0_ 
      And instrb(firstline, const_nameis) > 0 Then 
     ’ 得到表单域名称,就是<input type=sometype name=somename>里的somename。 
     fldname = B2S(midb(part1,_ 
               instrb(part1, const_nameis)+lenb(const_nameis),_ 
               instrb(part1, bncrlf)_ 
                 -instrb(part1, const_nameis)-lenb(const_nameis)-1)) 
     ’ 得到表单域的值 
     fldvalue = B2S(midb(part1,_ 
                instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf),_ 
                lenb(part1)-instrb(part1, bncrlf&bncrlf)+_ 
                                   lenb(bncrlf&bncrlf))) 
     If m_dicForms.Exists(fldname) Then 
       Set fElement = m_dicForms.Item(fldname) 
       m_dicForms.Remove fldname 
     Else 
       Set fElement = new FormElement 
     End If 

     fElement.Add fldname&"_"&fElement.Count, fldvalue 
     m_dicForms.Add fldname, fElement 

   ’有filename=",有name=",说明是一个文件单元 
   ’(这里还是有一个BUG,研究出来没?) 
   ElseIf instrb(firstline, const_filenameis) > 0_ 
          And instrb(firstline, const_nameis) > 0 Then 
     ’ 得到表单域名称,就是<input type=file name=somename>里的somename。 
     fldname = B2S(midb(part1,_ 
               instrb(part1, const_nameis)+lenb(const_nameis),_ 
               instrb(part1, const_filenameis)_ 
                 -instrb(part1, const_nameis)-lenb(const_nameis)-3)) 
     ’ 得到表单域的值 
     fldvalue = midb(part1,_ 
                instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf),_ 
                lenb(part1)-instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf)) 
     ’ 得到路径 
     filepath = B2S(midb(part1,_ 
               instrb(part1, const_filenameis)+lenb(const_filenameis),_ 
               instrb(part1, bncrlf)_ 
                 -instrb(part1, const_filenameis)-lenb(const_filenameis)-1)) 
     ’ 得到contenttype 
     contenttype = B2S(midb(part1,_ 
                   instrb(part1, bncrlf)+lenb(bncrlf)+14,_ 
                   instrb(part1,_ 
                          bncrlf&bncrlf)-instrb(part1, bncrlf)-_ 
                          lenb(bncrlf)-14)) 
     If lenb(fldvalue) > 0 Then ’size>0说明有文件传来了。 
       If m_dicFiles.Exists(fldname) Then 
         Set fElement = m_dicFiles.Item(fldname) 
         m_dicFiles.Remove fldname 
       Else 
         Set fElement = new FileElement 
         fElement.Rawdata = m_bRawData 
       End If 

       ’检查单个文件尺寸 
       If m_lMaxFileSize > 0 And m_lMaxFileSize < lenb(fldvalue) Then _ 
         err.raise 26,"TooLargeFile", "文件"&fldname&"尺寸过大" 
       m_lTotalBytes = m_lTotalBytes + lenb(fldvalue) 
       ’检查文件总尺寸 
       If m_lTotalMaxFileSize > 0 And m_lTotalMaxFileSize < m_lTotalBytes Then 
         err.raise 27,"TooLargeFiles", "文件总尺寸过大" 
       End If 
       ’检查文件类型 
       ext = right(filepath, len(filepath)-instrrev(filepath, ".")) 
       If m_strAllowedFilesList <> "" Then 
         afl = Split(m_strAllowedFilesList,"|") 
         isTypeError = True 
         For i = 0 To Ubound(afl) 
           ’找到了,允许 
           If ucase(trim(ext)) = ucase(trim(afl(i))) Then 
             isTypeError = False 
             Exit For 
           End If 
         Next 
         If isTypeError Then _ 
           err.raise 28,"InvalidFileType", "文件"&fldname&"类型错误" 
       End If 
       If m_strDeniedFilesList <> "" Then 
         dfl = Split(m_strDeniedFilesList,"|") 
         For i = 0 To Ubound(dfl) 
           ’找到了,不允许 
           If ucase(trim(ext)) = ucase(trim(dfl(i))) Then _ 
             err.raise 28,"InvalidFileType", "文件"&fldname&"类型错误" 
         Next 
       End If 

       fElement.Add fldname, fldvalue, contenttype, filepath 
       m_dicFiles.Add fldname, fElement 
     End If 
   End If 

   ’ 截取剩下的部分,递归调用这个函数,来得到下一个part1。 
   Call fillEveryFirstPart(rightb(data, lenb(data)-endpos-1)) 
 End Sub 

 ’ 这是一个公用函数,作用是二进制和字符串的转换 
 Private Function B2S(bstr) 
   Dim bchr, temp, i 
   If not IsNull(bstr) Then 
     for i = 0 to lenb(bstr) - 1 
       bchr = midb(bstr,i+1,1) 
       If ascb(bchr) > 127 Then ’遇到了双字节,就得两个字符一起处理 
         temp = temp & chr(ascw(midb(bstr, i+2, 1) & bchr)) 
         i = i+1 
       Else 
         temp = temp & chr(ascb(bchr)) 
       End If 
     next 
   End If 
   B2S = temp 
 End Function 

End Class 

’ 这是一个辅助类,为了实现ourRequest.Forms.Count功能。 
Class Counter 
 Private m_iCnt 

   ’ count是咱们这个类的一个只读属性 
 Public Property Get Count() 
   Count = m_iCnt 
 End Property 

 Public Function setCount(cnt) 
   m_iCnt = cnt 
 End Function 
End Class 
%> 


2。testform.html 
<form action="doupload.asp" method=post enctype="multipart/form-data"> 
 file1说明:<input type=text name=file1_desc> 
 file1:<input type=file name=file1><br> 
 file2说明:<input type=text name=file2_desc> 
 file2:<input type=file name=file2><br> 
 <input type=checkbox name=chk value=a>a 
 <input type=checkbox name=chk value=b>b 
 <input type=checkbox name=chk value=c>c 
 <input type=checkbox name=chk value=d>d 
 <input type=checkbox name=chk value=e>e<hr> 
 <input type=submit name=upload value=upload> 
</form> 


3。doupload.asp 
<%Option Explicit%> 
<!--#INCLUDE FILE="com.2yup.util.uploadrequest.class"--> 

<% 
’下面是测试码 
Dim ourRequest 
set ourRequest = new UploadRequest 
ourRequest.AllowedFilesList = "gif|doc" 
ourRequest.DeniedFilesList = "jpg" 
ourRequest.MaxFileSize = 10*1000 ’10k 
ourRequest.TotalMaxFileSize = 15*1000 ’15k 
on error resume next 
ourRequest.Upload 
if err.number <> 0 then 
 response.write err.description 
 response.end 
end if 
on error goto 0 ’关闭on error resume next 
%> 

<%=ourRequest.Form(0).Name%>:<%=ourRequest.Form("file1_desc")%><br> 
<%=ourRequest.Form(1).Name%>:<%=ourRequest.Form("file2_desc")%><br> 
<%=ourRequest.Form(2).Name%>:<%=ourRequest.Form(2).Count%><br> 
<%=ourRequest.Form(3).Name%>:<%=ourRequest.Form(3)%> 

一共有<%=ourRequest.Forms.Count%>个文本单元<hr> 

<%=ourRequest.File(0).Name%>: 
<%=ourRequest.File("file1").ContentType%>: 
<%=ourRequest.File("file1").Size%>byte: 
<%=ourRequest.File("file1").FileName%>: 
<%=ourRequest.File("file1").FilePath%><br> 

<%=ourRequest.File(1).Name%>: 
<%=ourRequest.File("file2").ContentType%>: 
<%=ourRequest.File("file2").Size%>byte: 
<%=ourRequest.File("file2").FileName%>: 
<%=ourRequest.File("file2").FilePath%><br> 

一共有<%=ourRequest.Files.Count%>个文件单元,共<%=ourRequest.TotalBytes%>Byte<hr> 

<% 
’测试存盘。 
Dim desFolder:desFolder=server.mappath("incoming") 
Call ourRequest.SaveTo(desFolder) 
Call ourRequest.File(0).SaveAs(desFolder, "复件 "&ourRequest.File(0).FileName) 
’因为选择了不覆盖的方法,所以第二次执行这一句会出错,一定要注意啊 
Call ourRequest.File("file2").SaveWithoutOverwrite(desFolder,_ 
                                "复件 "&ourRequest.File(1).FileName) 
%> 

<% 
’测试写库 
If False Then ’要测的话,就把False改成True。 

 ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ 
 ’ 数据库结构: 
 ’ ID       自增主键 
 ’ img      access里,用ole对象型;在sql server里,就应该是image型了 
 ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ 

 ’ 这部分没啥好说的。。 
 Dim connGraph, rec 
 set connGraph=server.CreateObject("ADODB.connection") 
 connGraph.ConnectionString="driver={Microsoft Access Driver (*.mdb)};DBQ=" &_ 
                             server.MapPath("img.mdb") 
 connGraph.Open 
 set rec=server.createobject("ADODB.recordset") 
 rec.Open "SELECT * FROM img where id is null",connGraph,1,3 
 rec.addnew 
 rec("img").appendchunk ourRequest.File(0) 
 rec.update 
 rec.close 
 set rec=nothing 
 set connGraph=nothing 

 ’ 读库代码如下。当然,读库显示是要在其他页面进行的。。 
 ’ 这部分也没啥好说的。不用contentType,IE也认。要是其他浏览器,就设一下。   
 ’set connGraph=server.CreateObject("ADODB.connection") 
 ’connGraph.ConnectionString="driver={Microsoft Access Driver (*.mdb)};DBQ=" &_ 
 ’                            server.MapPath("img.mdb") 
 ’connGraph.Open 
 ’set rec=server.createobject("ADODB.recordset") 
 ’rec.Open "SELECT * FROM img order by id desc",connGraph,1,1 
 ’response.BinaryWrite rec("img") 
 ’rec.close 
 ’set rec=nothing 
 ’set connGraph=nothing 
End If 
%> 

<% 
’清理资源,别忘了啊 
Set ourRequest = Nothing 
%> 


好了,把这3个文件保存到一个虚拟目录下,然后,建立一个incoming的子目录,并且给足权限(关于权限,看看http://www.2yup.com/asp/forum/branch.asp?pid=2430#F0002430),就可以测试了。现在,一个功能强大的无组件上传类就已经完成了。 


============================================================== 
结束语 

这里演示了文件上传从分析倒实践的全过程。通过不懈的努力,我们终于达到了预定的目标。当然,这个实现,和“完美”尚有差距。他没有经过严格测试;还存在至少两个BUG;还有几个蹩脚的实现。这些,都是值的改进的。但是,如果能掌握这个示例的完整过程,相信大家也可以胜任各种复杂的应用,能够独立的完成一般的设计和编码工作了。所以,我们的收获,绝不仅仅是知道了怎样上传一个文件,更多的,是知道了怎样达到一个目标。最后,附上整个示例的源码和用到的库。刚刚(2002-12-02 09:00)才进行了更新,做了一个自认为比较清晰的例子。不需要看懂,就可以用了 ^ ^: 

http://www.2yup.com/asp/attach/A0000006.zip 

注意,把这个包里的东西放到一个虚拟目录下,其中的incoming子目录一定要有IUSR的写权限(关于权限,看看http://www.2yup.com/asp/forum/branch.asp?pid=2430#F0002430)。有任何问题,请到论坛提出。  
文章页数:[1] 
帮助你我他: 1.我有问题请教 2.我要投稿>>>
更多相关资料搜索:
热点文章
最新文章
相关文章
版权申明:除部分特别声明不要转载,或者授权本站独家播发的文章外,大家可以自由转载本站的原创文章,但原作者和来自本站的链接必须保留(非本站原创的,按照原来自一节,自行链接)。文章版权归本站和作者共有。
转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去本站水印。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论  打印  刷新  推荐给朋友  返回顶部  关闭

网上大名: