ASP

本类阅读TOP10

·asp常用数据库连接方法和技巧
·无组件生成BMP验证码
·一些常用的辅助代码 (网络收藏)
·JavaScript实现的数据表格:冻结列、调整列宽和客户端排序
·VisualStudio.NET_2003及其 MSDN 下载地址
·ASP模拟MVC模式编程
·图片以二进制流输出到网页
·MD5加密算法 ASP版
·ASP.NET编程中的十大技巧
·改进 ASP 的字符串处理性能

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
ASP文件上传神功 第三重(招势图加内功心法)

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

第三重:集成类、多语种通用,使用方便

  这个问题已经不是什么新鲜问题了,网上也有大把的教程,但大多数是授人以鱼,而不授人以渔,经过辛苦的资料收集,思考,调试,整理,我基本上已经把这个问题从原理上搞清楚了,现在根据我自己的理解,在范例程序的基础上,加以解释,希望能对部分网友(比我还菜的:-))有所帮助。

  请诸位大虾能对其中的不正或不良这处予以指正。

  程序中stream对象的用法上参考了“化境HTTP上传程序 Version 2.0”在代码,在此对稻香老农梁无惧表示衷心的感谢和由衷的敬意。

  先来分析一下,为后面的数据分析算法打点基础,以下是我摘录的一小段网页中提交的二进制数据:
-----------------------------7d31ec15102d0
Content-Disposition: form-data; name="txtTitle"

满脑的想法
-----------------------------7d31ec15102d0
Content-Disposition: form-data; name="filImage"; filename="F:\material\木纹背景\pic016.jpg"
Content-Type: image/pjpeg

? JFIF      C 

 !!E.'.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE?"             
?   } !1AQa"q2亼?#B绷R佯$3br?
侼s歊J佦=ǜ珻,%??Xm 銓鼽?幮??驲湕胄滙C?
儗 g?咶? tS?B矠:u隠c
g不t凄L琰h`啨0p
 g殲41?9'$筵奆]眬?膁?摍? 渦"??
-----------------------------7d31ec15102d0
Content-Disposition: form-data; name="btnUpload"

Upload
-----------------------------7d31ec15102d0--

  蓝色的字符的内容我们应该熟悉吧,中间的乱码就是上传的文件的内容,其实我们要做的就是将这一堆数据进行分析,挑出对我们有用的数据保存下来就OK了。分析数据就是查找一些标志性的内容,如回车换行符,“----------”符号,用两个指针确定两个位置,然后提取数据,我的算法不知道好不好,本人的数据结构是学得很烂的,十分sorry。

以下是一个完事的应用,其中的类定义可以与入另一个文件,使用的时候只要用

 <!--include file="LjUpload.cls"-->

命令包含进来就可以了。

LjUpload.asp:

<%@ Language=VBScript %>
<% option explicit %>

<script language=vbscript runat=server>

 private srmRequestData   'adodb.stream对象,保存从form中提交来的所有数据

 private adTypeBinary   'adodb.stream对象的叁数:返回二进制数据
 private adTypeText   'adodb.stream对象的叁数:返回文本数据
 private adModeRead   'adodb.stream对象的叁数:对象可读
 private adModeWrite   'adodb.stream对象的叁数:对象可写
 private adModeReadWrite   'adodb.stream对象的叁数:对象可读写

 class LjUpload   '定义一个类,名称为LjUpload。
  
  private bytCrLf   '单字节的回车换行符,共2字节
  private bytSub   '单字节的“-”符号,共8字节
  private binData    '二进制数据变量,保存一个提交数据的复本,便於操作

  private dicForm   '保存form文本域的信息
  private dicFile   '保存form文件域的信息
  private strName   'form表单的输入域名称
  private strValue   'form表单的输入域值
  private objFile   '文件信息对象,保存文件相关的信息,具体叁看class LjFile的定义

  private posB   '二进制数据读写指针,开始指针
  private posE   '二进制数据读写指针,结束指针
  public Charset   '语言属性设置
  
  private sub Class_Initialize   '类初始化过程
   
   bytCrLf = getSBfromDB(vbcrlf)
   bytSub = getSBfromDB("--------")
   Charset = "gb2312"   '默认语言属性设置为简体中文:gb2312
   
   adTypeBinary = 1   '返回二进制数据
   adTypeText = 2   '返回文本数据
   adModeRead = 1   '对象数据可读
   adModeWrite = 2   '对象数据可写
   adModeReadWrite = 3   '对象数据可读写
  end sub
  
  public sub GetData   '类的打开过程,上传文件及分析数据的过程
   
   set srmRequestData = server.CreateObject("adodb.stream")   '建立一个adodb.stream对象
   
   srmRequestData.Type = adTypeBinary   '指定返回数据类型
   srmRequestData.Mode = adModeReadWrite   '指定打开模式
   srmRequestData.Open   '打开对象
   srmRequestData.Write request.BinaryRead(request.TotalBytes)   '获取所有form提交的数据
   
   srmRequestData.Position = 0   '读写指针重新定位至对象头部,写数据,指针已指向对象尾
   binData = srmRequestData.Read   '在变量中保存提交数据的复本,便於操作
   
   set dicForm = server.CreateObject("scripting.dictionary") '用来保存文本信息
   set dicFile = server.CreateObject("scripting.dictionary") '用来保存文件信息

   posB = instrb(binData,bytSub)   '开始分析所获取的二进制数据
   posB = instrb(posB,binData,bytCrLf) + 2 '+2是加入回车换行符本身的长度
   posB = instrb(posB,binData,getSBfromDB("name=""")) + 6
   do until posB = 6   '控制条件的设置有多种方式,这里的仅供叁考
    posE = instrb(posB,binData,getSBfromDB(""""))
    strName = getTextfromBin(srmRequestData,posB,posE-posB)
   
    posB = posE + 1 '指针移动到“"”的後面
    posE = instrb(posB,binData,bytCrLf)
    
    if instrb(midb(binData,posB,posE-posB),getSBfromDB("filename=""")) > 0 then '这是一个file域
     posB = instrb(posB,binData,getSBfromDB("filename=""")) + 10
     posE = instrb(posB,binData,getSBfromDB(""""))
     set objFile = new LjFile   '建立一个文件信息对象
     if posE>posB then
      objFile.FileName = getFileNamefromPath(getTextfromBin(srmRequestData,posB,posE-posB))   '写入文件名称
      posB = instrb(posB,binData,getSBfromDb("Content-Type:")) + 14
      posE = instrb(posB,binData,bytCrLf)
      objFile.ContentType = getTextfromBin(srmRequestData,posB,posE-posB)   '写入文件类型
      posB = posE + 4   '这个地方换了两行,具体叁看输出的原始二进制数据
      posE = instrb(posB,binData,bytSub)
      objFile.FileBegin = posB
      objFile.FileLen = posE-posB-2   '写入文件长度信息,-2是减去一个回车符
     end if
     dicFile.Add strName, objFile
     set objFile = nothing   '释放文件信息对象
    else   '这是一个文本域
     posB = posE + 4 '这个地方换了两行,具体叁看输出的原始二进制数据
     posE = instrb(posB,binData,bytSub) - 2
     strValue = getTextfromBin(srmRequestData,posB,posE-posB)
     dicForm.Add strName, strValue
    end if
    posB = posE + 2
    posB = instrb(posB,binData,bytCrLf) + 2
    posB = instrb(posB,binData,getSBfromDB("name=""")) + 6
   loop   '当循环结束时分析二进制数据完成
  end sub
  
  private function getTextfromBin(srmSource,posBegin,posLen)   '二进制数据转换为字符串,包括汉字
   dim srmObj, strData
   set srmObj = server.CreateObject("adodb.stream")
   srmObj.Type = 1
   srmObj.Mode = 3
   srmObj.Open
   srmSource.position = posBegin-1 '位置计数首数不一样,这个对像是对0开始的
   srmSource.CopyTo srmObj,posLen
   srmObj.Position = 0
   srmObj.Type = 2
   srmObj.Charset = Charset    '语言属性设置
   strData = srmObj.ReadText
   srmObj.Close
   set srmObj = nothing
   getTextfromBin = strData
  end function

  private function getSBfromDB(bytString)   '双字节字符串转换成单字节字符串
   dim bin, i
   bin = ""
   for  i=1 to len(bytString)
   bin = bin & chrb(asc(mid(bytString,i,1)))
   next
   getSBfromDB = bin
  end function

  private function getDBfromSB(bitString)   '单字节字符串转换成双字节字符串
   dim str, i
   str = ""
   for i=1 to lenb(bitString)
   str = str & chr(ascb(midb(bitString,i,1)))
   next
   getDBfromSB = str
  end function

  private function getFileNamefromPath(strPath)   '从一个完整路径中析出文件名称
   getFileNamefromPath = mid(strPath,instrrev(strPath,"\")+1)
  end function

  public sub about()  '关於类过程
   dim html
   html = "<table border=1 cellpadding=2 cellspacing=1>" & "<tr>" & _
       "<td style='font-family:verdana;' bgcolor=yellow> <marquee width=160 " & _
       "onmouseover='this.stop();' onmouseout='this.start();'>" & _
       "<a href=mailto:[email protected] target=_blank>LiJun Upload Class V1.0</a>" & _
       "</marquee> </td>" & "</tr>" & "</table>"
   Response.Write html
  end sub
  
  public function Form(strFormName)  '求表单内容的函数
   if dicForm.Exists(strFormName) then
    Form = dicForm(strFormName)
   else
    Form = ""
   end if
  end function
  
  public function File(strFormName)  '求文件内容的函数
   if dicFile.Exists(strFormName) then
    set File = dicFile(strFormName)
   else
    set File = new LjFile
   end if
  end function
  
  private sub Class_Terminate   '类终止过程
   dicForm.RemoveAll
   set dicForm = nothing
   dicFile.RemoveAll
   set dicFile = nothing
   srmRequestData.Close
   set srmRequestData = nothing
  end sub
  
 end class

 class LjFile   '文件类
  public FileName   '文件名
  public ContentType   '文件类型
  public FileBegin   '文件数据开始位置
  public FileLen   '文件长度,字节数
  private sub Class_Initalize
   FileName = ""
   ContentType = ""
   FileBegin = 0
   FileLen = 0
  end sub
  public sub SaveToFile(FilePath)   '文件保存到磁盘上,FilePath为完整路径,包括文件名
   dim srmObj
   set srmObj = server.CreateObject("adodb.stream")
   srmObj.Type = adTypeBinary
   srmObj.Mode = adModeReadWrite
   srmObj.Open
   srmRequestData.Position = FileBegin-1
   srmRequestData.CopyTo srmObj, FileLen
   srmObj.Position = 0
   srmObj.SaveToFile FilePath, 2   '如果该文件已经存在,无条件覆盖,以後根据需要再行完善
   srmObj.Close
   set srmObj = nothing
  end sub
  public function GetBinaryData()
   srmRequestData.Position = FileBegin-1
   GetBinaryData = srmRequestData.Read(FileLen)
  end function
 end class
</script>

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
<meta http-equiv="content" content="text/html;charset=gb2312">
<TITLE>ASP无组件上传类:LjUpload</TITLE>
</HEAD>
<BODY>
<%
if request.ServerVariables("REQUEST_METHOD") = "POST" then

 dim upload
 set upload = new LjUpload
 upload.Charset = "gb2312"   '设置文本信息的语言属性
 upload.GetData()
 
 dim title, filImage
 title = upload.Form("txtTitle")
 Response.Write title & "<br>"
 set filImage = new LjFile   '这句可不用,此处仅为写代码方便
 set filImage = upload.File("filImage")
 Response.Write filImage.FileName & "<br>"
' 以文件形式保存到磁盘,文件名是当前日期时间的处理值
 filImage.SaveToFile server.MapPath("./") & "\" & replace(replace(replace(now(),"/","_")," ","_"),":","_") & "." & right(filImage.FileName,3)
 
' 保存到数据库用以下的代码
' dim cn, rs, sql
' set cn = server.CreateObject("adodb.connection")
' cn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & server.MapPath("upload.mdb")
' set rs = server.CreateObject("adodb.recordset")
' sql = "select title,[content-type],image from tblImage"
' rs.Open sql,cn,1,3
' rs.AddNew
' rs.Fields("title").Value = title
' rs.Fields("content-type").Value = filImage.ContentType

' rs.Fields("image").AppendChunk filImage.GetBinaryData()

' rs.Update
' rs.Close
' set rs = nothing
' cn.Close
' set cn = nothing

 upload.about()   '关於类信息
 
 set filImage = nothing
 set upload = nothing
end if
%>
 <form id="frmUpload" name="frmUpload" action="<%=Request.ServerVariables("script_name")%>" method="post" target="_self" enctype="multipart/form-data">
 <p>标题:<input id="txtTitle" type="text" name="txtTitle" size="40"></p>
 <p>图片:<INPUT id="filImage" type="file" name="filImage" size="40"></p>
 <INPUT id="btnUpload" type="submit" value="Upload" name="btnUpload">
 </form>
</BODY>
</HTML>

完。




相关文章

相关软件