第三重:集成类、多语种通用,使用方便
这个问题已经不是什么新鲜问题了,网上也有大把的教程,但大多数是授人以鱼,而不授人以渔,经过辛苦的资料收集,思考,调试,整理,我基本上已经把这个问题从原理上搞清楚了,现在根据我自己的理解,在范例程序的基础上,加以解释,希望能对部分网友(比我还菜的:-))有所帮助。
请诸位大虾能对其中的不正或不良这处予以指正。
程序中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:java300@163com 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>
完。
本文地址:http://com.8s8s.com/it/it9128.htm