最近参与了一个网站开发的项目,在做后台管理时用到了文件上传,因为客户要求数据库保存的是文件路径,文件就得直接上传到服务器,而且麻烦的是需要把其他表单信息和上传的图片一起进行数据处理,这样就不能用Request.Form来得到表单信息,只能以二进制的方式进行处理。现就以我开发的项目为例来说明如何以二进制方式来处理表单数据。
< table width ="590" >
< tr >
< td align ="center" > 新增教学点(带 < font color =red > * </ font > 的为必填字段) </ td >
</ tr >
</ table >
< table width ="590" border ="1" >
< tr >
< td align ="right" > 教学点ID: </ td >
< td >< input name ="CenterID2" type ="text" maxlength ="3" /> < font color =red > * </ font ></ td >
< td > 唯一性3位代码,如“LJD”=临时西南交大 </ td >
</ tr >
< tr >
< td align ="right" > 教学点名称: </ td >
< td >< input name ="CenterName2" type ="text" /> < font color =red > * </ font ></ td >
< td > </ td >
</ tr >
< tr >
< td align ="right" > 教学点地址: </ td >
< td >< input name ="CenterAddress2" type ="text" size ="40" /></ td >
< td > </ td >
</ tr >
< tr >
< td align ="right" > 教学点电话: </ td >
< td >< input name ="CenterPhone2" type ="text" size ="40" /></ td >
< td > </ td >
</ tr >
< tr >
< td align ="right" > 教学点交通指南信息: </ td >
< td >< textarea name ="CenterTraffic2" cols ="40" rows ="6" ></ textarea ></ td >
< td > 多条线路之间用“;”分隔,如“乘坐16和99路在人民南路四段北站下; 乘坐303、78、61、45、12、19、27和34路在跳伞塔路口下”
</ tr >
< tr >
< td align ="right" width ="120" > 教学点示意图: </ td >
< td width ="290" align ="center" >< input name ="image" type ="file" >
< td > 教学点的图片表示,长宽比xx:xx的jpg文件,文件名格式:DDmaps+教学点ID.jpg,如“DDmapsLJD.jpg” </ td >
</ tr >
< tr >
< td colspan ="3" align ="center" >< input name ="submit" type ="submit" value ="增加" />
< input type ="reset" name ="reset" value ="重置" /></ td >
</ tr >
</ table >
</ form >
需要注意的是Form里一定要包含enctype="multipart/form-data"这句话。下面我们来看看以二进制方式读取表单的代码:
filedata = Request.BinaryRead(filesize) ' filedata是表单的二进制数据
以上面的方式读取表单后,我们再用下面的语句在浏览器中查看表单中输入的数据是怎么表示的:
现在让我们看看表单的二进制表示方式吧:
-----------------------------7d733c3240e98 Content-Disposition: form-data; name="CenterID2" TEP -----------------------------7d733c3240e98 Content-Disposition: form-data; name="CenterName2" tempCenter -----------------------------7d733c3240e98 Content-Disposition: form-data; name="CenterAddress2" RenMinRoad -----------------------------7d733c3240e98 Content-Disposition: form-data; name="CenterPhone2" 88888888 -----------------------------7d733c3240e98 Content-Disposition: form-data; name="CenterTraffic2" -----------------------------7d733c3240e98 Content-Disposition: form-data; name="image"; filename="C:/Documents and Settings/milanello/My Documents/My Pictures/AC Milan.jpg" Content-Type: image/pjpeg ?JFIFddDucky&Adobed &&))&&87778>>>>>>>>>> ''#% %#++''++55355>>>>>>>>>>22"!1Aa"Qq?4?BsDb偄#1Aa!Qq?? ?樵?Y儆b?ead桺 eF踨鏏斢斷觠鋭餲絴=G烩c榩/,鵵0恆猝? 交lΒl垲躾y銦n|? Yku憯泍sA缛謎G啐1攆棥F拞?缺%凂y]=岴)J襐)JP 徃fG亙憶/饲崵n?鲽詩??h?榃鮵j}谠熉幠臯Isiqr3r檞,?k 霊簬惴?"E鶲;蜥S2鍙q8K氹封g?T剎?V堩s{/p?厷i塮i?菈$€I5?龜磍傻?J?猛V!An<m獰祄N迖?敠咎安p蕯诒H鑎栜g馅攅齨#?_頓t擇5qX這淞6V跻腴L裆悅?穭胤-6鏪*???3i琟珪t?NQz?昌1?峀?鲐;?{^:+?€世哠葍缞2b栌潢p萸k死)4藎l梻/l?霊 ??h飙:1?颐丈z鋳#x?酮f^)儇m朌樆r楙^幛?IY]牃軝t貽}<睾灈訖彎窵?hF渪a攊?,;盱獢謻嵊辈_з$紃n蚆I6﨓竣遛3?z湶奡俍!o魝?旱5h踑诙? 鈵-?l菋1鲹z橵?漘 YtV?@?@G销I~W/鋦瞑?臃瑶o鄚繌})@X覕??? -----------------------------7d733c3240e98 Content-Disposition: form-data; name="submit" 增加 -----------------------------7d733c3240e98--
分析浏览器上显示的二进制代码,发现每一段代码包括四个部分,每一部分的内容是用回车换行符号来进行分隔的:
1 )第一部分(起始标志)
-----------------------------7d733c3240e98
2 )第二部分(文件说明)
如:Content-Disposition: form-data; name="CenterID2"
3 )第三部分(文件内容)
如果是其他表单内容,如文本框,则是你输入的内容,如TEP,而文件框则是你上传文件的二进制代码,就像上面那段代码中显示的乱码一样。
4 )第四部分(结束标志)
-----------------------------7d733c3240e98
下面是完整的处理表单的代码:
newline = chrB( 13 ) & chrB( 10 ) ' newline表示二进制的回车符
filesize = Request.TotalBytes ' filesize是表单数据大小
filedata = Request.BinaryRead(filesize) ' filedata是表单的二进制数据
divider = leftB(filedata, clng (instrb(filedata,newline)) - 1 ) ' divider是分割符
set rst = Server.CreateObject( " ADODB.Recordset " )
rst.open " Center " ,bb, 1 , 3
rst.Addnew
k = 1
While instrb(k,filedata,divider) < instrb((instrb(k,filedata,divider) + lenb(divider)),filedata,divider)
start = instrb(k,filedata,divider) + lenb(divider) + 2
endsize = instrb((instrb(k,filedata,divider) + lenb(divider)),filedata,divider) - start - 2
content = midb(filedata,start,endsize) ' 取文件说明部分
start_name = instrb(content,toByte( " name="" " ))
end_name = instrb(start_name + 6 ,content,toByte( " "" " ))
nametag = midb(content,start_name + 6 ,end_name - start_name - 6 ) ' 取文件说明部分中name=""中的内容,即表单元素的名称
pos1_filename = instrb(end_name,content,toByte( " filename="" " )) ' 如果是文件框,则文件说明部分应有filename="",那么pos1_filename不等于0
If pos1_filename = 0 Then ' 表单中不属于文件上传的数据处理
namevalue = toStr(midb(content,end_name + 5 ,lenb(content) - end_name - 4 )) ' 取文件内容
' 将文件说明部分的name=""中的内容与表单元素的名称进行比较,把相应的内容加入数据库
If ( InStr (toStr(nametag), " CenterID2 " ) > 0 ) Then
rst( " CenterID " ) = namevalue
session( " CenterID " ) = namevalue ' 用于上传文件保存时的文件名中
End If
If ( InStr (toStr(nametag), " CenterName2 " ) > 0 ) Then
rst( " CenterName " ) = namevalue
End If
If ( InStr (toStr(nametag), " CenterAddress2 " ) > 0 ) Then
rst( " CenterAddress " ) = namevalue
End If
If ( InStr (toStr(nametag), " CenterPhone2 " ) > 0 ) Then
rst( " CenterTel " ) = namevalue
End If
If ( InStr (toStr(nametag), " CenterTraffic2 " ) > 0 ) Then
rst( " CenterTraffic " ) = namevalue
End If
' Response.Write (namevalue)
' Response.Write("<br>")
else ' 处理文件上传部分的数据
pos2_filename = instrb(pos1_filename + 10 ,content,toByte( " "" " ))
fullpath = midb(content,pos1_filename + 10 ,pos2_filename - pos1_filename - 10 ) ' 从文件说明部分中取出文件路径
If (fullpath <> "" ) Then ' 如果有上传的文件,执行以下代码
dim bStart ' 取二进制流文件部分开始位置
bStart = instrb(start,filedata,newline & newline) + 3
dim bEnd ' 取二进制流文件部分结束位置
bEnd = inStrB(bStart + 6 ,filedata,divider) - bStart - 3
dim stm ' 定义一个 adodb.stream 源对象 stm, 用以拷贝二进制流文件部分至另一 adodb.stream fromStm
set stm = createObject ( " adodb.stream " )
stm.type = 1 ' 二进制模式
stm.mode = 3 ' 指定打开模式为读写
stm.open
stm.write filedata ' 写入二进制流内容
dim fromStm ' 定义 adodb.stream 对象 fromStm, 以保存文件
set fromStm = createOBject ( " adodb.stream " )
with fromStm
.type = 1
.mode = 3
.open
stm.position = bStart ' 指定 stm 对象的起始位置, 以变量 bStart 的值为起始位置
stm.copyTo fromStm, bEnd ' 拷贝 stm 二进制流至 fromStm 对象, 长度为 bEnd 变量的长度
.saveTofile server.MapPath( " ./ " ) & " imageDDmap " & session( " CenterID " ) & " .jpg " , 2 ' 保存文件, 如果存在相同名称, 则覆盖
.close
end with
set fromStm = nothing
stm.close
set stm = nothing
rst( " CenterMap " ) = " Image/DDmap " & session( " CenterID " ) & " .jpg " ' 将文件的相对路径写入数据库中
end if
end if
k = instrb((instrb(k,filedata,divider) + lenb(divider)),filedata,divider)
Wend
rst.update
rst.close
set rst = nothing
session.abandon
end if
function toStr(Byt) ' 将二进制转换为字符串
toStr = ""
for i = 1 to lenb(byt)
blow = midb(byt,i, 1 )
if ascb(blow) > 127 then
toStr = toStr & chr (ascw(midb(byt,i + 1 , 1 ) & blow)) '
i = i + 1
else
toStr = toStr & chr (ascb(blow))
end if
Next
End function
Function toByte(Str) ' 将字符串转换为二进制
dim i,iCode,c,iLow,iHigh
toByte = ""
For i = 1 To Len (Str)
c = mid (Str,i, 1 )
iCode = Asc (c)
If iCode < 0 Then iCode = iCode + 65535
If iCode > 255 Then
iLow = Left ( Hex ( Asc (c)), 2 )
iHigh = Right ( Hex ( Asc (c)), 2 )
toByte = toByte & chrB( " &H " & iLow) & chrB( " &H " & iHigh)
Else
toByte = toByte & chrB(AscB(c))
End If
Next
End function
总结,以上例子只是上传文件的一种方法,当应用不同时,处理的方法应随机应变,希望这篇文章能起到抛砖引玉的作用。