这个问题已经不是什么新鲜问题了,网上也有大把的教程,但大多数是授人以鱼,而不授人以渔,经过辛苦的资料收集,思考,调试,整理,我基本上已经把这个问题从原理上搞清楚了,现在根据我自己的理解,在范例程序的基础上,加以解释,希望能对部分网友(比我还菜的:-))有所帮助。
请诸位大虾能对其中的不正或不良这处予以指正。
程序中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'定义 桓隼啵莆狶jUpload。 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,bytCrLf) 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 FileInfo 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>
完。
|