首先是网上的一个经典上传代码:
一.submit.htm
<html><title>example</title>
<body>
<form name="form1" method="post" action="upload.asp" enctype="multipart/form-data">
<input type=file name="myfile">
<input type=submit name="submit" value="提交">
</form>
</body>
</html>
二.upload.asp
<%@ Language=VBScript %>
<%
function binarytoasi(byval varstr)
asi=""
for i=1 to 3
asi=asi&chr(ascb(midb(varstr,i,1)))
next
binarytoasi=asi
end function
formsize=request.totalbytes
formdata=request.binaryread(request.totalbytes ) '获得上传数据
bcrlf=chrB(13) & chrB(10)
divider=leftB(formdata,clng(instrb(formdata,bcrlf))-1)
Position=instrb(formdata,bcrlf & bcrlf)+4 '上传文档数据开始字节位置
filesize=instrb(Position+1,formdata,divider)-Position-4 '上传文档的总长度 注:这个位置有错,应改成-2
exnamestart=instrb(1,formdata,chrb(46),1)+1 ' 取扩展名的开始位置
exnameend=instrb(exnamestart,formdata,chrb(34),1) ' 取扩展名的结束位置
exname=midb(formdata,exnamestart,exnameend-exnamestart) ' 取扩展名
set dr=CreateObject("Adodb.Stream")
dr.Mode=3: dr.Type=1:dr.Open
set dr1=CreateObject("Adodb.Stream")
dr1.Mode=3:dr1.Type=1:dr1.Open
dr.Write formdata
dr.Position=Position-1
dr.CopyTo dr1,filesize
dr1.SaveToFile "d:/test/temp_"&"."&binarytoasi(exname),2 ' 文档保存
set dr=nothing:set dr1=nothing
%>
分析:第一. 上传通过:<input type=file name="myfile">以及<form name="form1" method="post" action="upload.asp" enctype="multipart/form-data">中的enctype="multipart/form-data" 这种方式,就会在提交时产生如下FORM包括的控件及文件myfiler的内容:
注:<input ...>的TYPE的值有:
button checkbox file hidden image password radio reset submit text
原TXT文件内容:
2008好运之年![坚师傅电脑维修中心]正式开张,电脑杀毒、远程维护、家庭组网....统一价:38元(新张8折)。
通过在upload.asp中<%Response.BinaryWrite FormData %>输入提交后接收到的所有内容
-----------------------------7d81191c10748 Content-Disposition: form-data; name="file1"; filename="D:\Documents and Settings\Administrator\My Documents\2008好运之年.txt" Content-Type: text/plain 2008好运之年![坚师傅电脑维修中心]正式开张,电脑杀毒、远程维护、家庭组网....统一价:38元(新张8折)。 -----------------------------7d81191c10748 Content-Disposition: form-data; name="submit" 提交 -----------------------------7d81191c10748--
如何取得文件的开始字节位置:
红色字部分是一个分隔符,每次长度及名称都不同,但同一次提交3个是相同的,而且通过WINHEX软件查看到文章内容的开始处肯定有0D0A0D0A(蓝色字中间的空格的内容的二进制值)如图:
所以通过:
bcrlf=chrB(13) & chrB(10) '0D0A的二进制值
Position=instrb(formdata,bcrlf & bcrlf)+4
注:InStr 函数
找到0D后要+4个字节才是文章的开始字节。
如何取得文件的长度:
试过通过文件结束处的0D0A,用Fileend=instrb(Position+1,formdata,bcrlf)-1,找到文件最后一个字节
文件长度=Fileend-Position+1
有个问题就是小文件可以,大文件时,文件中可能有许多0D0A,这样就出错了!
正确方法是:找到文件内容后的分隔符位置,再-2(原程序中-4不知是什么原因,会造成txt,jpg文件(少了两个字节)上传后打开正常,而RAR,EXE,GIF就打开出错)再-文件开始位置,即:
filesize=instrb(Position+1,formdata,divider)-2-Position
如何提取分隔符的字串值:
divider=leftB(formdata,clng(instrb(formdata,bcrlf))-1)
instrb(formdata,bcrlf) 定位在第一个0D0A的OD上,-1就定位在分隔符的最后一个字节上。
注:leftB(str,num) 从左边起取str的多少个字节, clng(str)将字串转成Long型数值。
为什么要set dr=CreateObject("Adodb.Stream")和set dr1=CreateObject("Adodb.Stream")
要产生两个Adodb.Stream对象
由于SaveToFile方法,只能全部保存通过dr.Write formdata 写入缓冲区的数据,而formdata不只是文件的数据,可通过copyto方法(可以从dr.position开始的,长度为filesize的数据)将所要用的文件数据利用dr作源,复制到目的dr1,将生成文件。
为什么要dr.position=position-1 而不是dr.position=position 因为position就是文件的第一个字节了!
经实践发现,生成Adodb.Stream对象,文件指针位置为0,无论读写文件,都是先将文件指针position+1后再读写字节数据,所以要生成文件前,要将文件指针先-1!
常见的两个错误:
1.当上传文件超过200KB时,报错:“请求对象错误 'ASP 0104 : 80004005' 操作被禁止 /Upload.asp, line 40 ”
因IIS6限制了上传大小为200KB
解决:先将IIS属性中的“允许直接编辑配置数据库”勾选
再找到 XX:\Windows\System32\Inetsrv 中的 metabase.XML, 修改 AspMaxRequestEntityAllowed=204800(200KB)。
2.当文件上传限制已改为200MB后,上传文件大于4MB时,报错:“Response 对象 错误 'ASP 0251 : 80004005'
超过响应缓冲区限制 /showuser.asp,行 0 此 ASP 页的执行造成响应缓冲区超过其配置限制。”
解决办法:找到 XX:\Windows\System32\Inetsrv 中的 metabase.XML, 修改 AspBufferingLimit="4194304"(4MB)。
一.submit.htm
<html><title>example</title>
<body>
<form name="form1" method="post" action="upload.asp" enctype="multipart/form-data">
<input type=file name="myfile">
<input type=submit name="submit" value="提交">
</form>
</body>
</html>
二.upload.asp
<%@ Language=VBScript %>
<%
function binarytoasi(byval varstr)
asi=""
for i=1 to 3
asi=asi&chr(ascb(midb(varstr,i,1)))
next
binarytoasi=asi
end function
formsize=request.totalbytes
formdata=request.binaryread(request.totalbytes ) '获得上传数据
bcrlf=chrB(13) & chrB(10)
divider=leftB(formdata,clng(instrb(formdata,bcrlf))-1)
Position=instrb(formdata,bcrlf & bcrlf)+4 '上传文档数据开始字节位置
filesize=instrb(Position+1,formdata,divider)-Position-4 '上传文档的总长度 注:这个位置有错,应改成-2
exnamestart=instrb(1,formdata,chrb(46),1)+1 ' 取扩展名的开始位置
exnameend=instrb(exnamestart,formdata,chrb(34),1) ' 取扩展名的结束位置
exname=midb(formdata,exnamestart,exnameend-exnamestart) ' 取扩展名
set dr=CreateObject("Adodb.Stream")
dr.Mode=3: dr.Type=1:dr.Open
set dr1=CreateObject("Adodb.Stream")
dr1.Mode=3:dr1.Type=1:dr1.Open
dr.Write formdata
dr.Position=Position-1
dr.CopyTo dr1,filesize
dr1.SaveToFile "d:/test/temp_"&"."&binarytoasi(exname),2 ' 文档保存
set dr=nothing:set dr1=nothing
%>
分析:第一. 上传通过:<input type=file name="myfile">以及<form name="form1" method="post" action="upload.asp" enctype="multipart/form-data">中的enctype="multipart/form-data" 这种方式,就会在提交时产生如下FORM包括的控件及文件myfiler的内容:
注:<input ...>的TYPE的值有:
button checkbox file hidden image password radio reset submit text
原TXT文件内容:
2008好运之年![坚师傅电脑维修中心]正式开张,电脑杀毒、远程维护、家庭组网....统一价:38元(新张8折)。
通过在upload.asp中<%Response.BinaryWrite FormData %>输入提交后接收到的所有内容
-----------------------------7d81191c10748 Content-Disposition: form-data; name="file1"; filename="D:\Documents and Settings\Administrator\My Documents\2008好运之年.txt" Content-Type: text/plain 2008好运之年![坚师傅电脑维修中心]正式开张,电脑杀毒、远程维护、家庭组网....统一价:38元(新张8折)。 -----------------------------7d81191c10748 Content-Disposition: form-data; name="submit" 提交 -----------------------------7d81191c10748--
如何取得文件的开始字节位置:
红色字部分是一个分隔符,每次长度及名称都不同,但同一次提交3个是相同的,而且通过WINHEX软件查看到文章内容的开始处肯定有0D0A0D0A(蓝色字中间的空格的内容的二进制值)如图:
所以通过:
bcrlf=chrB(13) & chrB(10) '0D0A的二进制值
Position=instrb(formdata,bcrlf & bcrlf)+4
注:InStr 函数
InStr([start, ]string1, string2[, compare])
找到0D后要+4个字节才是文章的开始字节。
如何取得文件的长度:
试过通过文件结束处的0D0A,用Fileend=instrb(Position+1,formdata,bcrlf)-1,找到文件最后一个字节
文件长度=Fileend-Position+1
有个问题就是小文件可以,大文件时,文件中可能有许多0D0A,这样就出错了!
正确方法是:找到文件内容后的分隔符位置,再-2(原程序中-4不知是什么原因,会造成txt,jpg文件(少了两个字节)上传后打开正常,而RAR,EXE,GIF就打开出错)再-文件开始位置,即:
filesize=instrb(Position+1,formdata,divider)-2-Position
如何提取分隔符的字串值:
divider=leftB(formdata,clng(instrb(formdata,bcrlf))-1)
instrb(formdata,bcrlf) 定位在第一个0D0A的OD上,-1就定位在分隔符的最后一个字节上。
注:leftB(str,num) 从左边起取str的多少个字节, clng(str)将字串转成Long型数值。
为什么要set dr=CreateObject("Adodb.Stream")和set dr1=CreateObject("Adodb.Stream")
要产生两个Adodb.Stream对象
由于SaveToFile方法,只能全部保存通过dr.Write formdata 写入缓冲区的数据,而formdata不只是文件的数据,可通过copyto方法(可以从dr.position开始的,长度为filesize的数据)将所要用的文件数据利用dr作源,复制到目的dr1,将生成文件。
为什么要dr.position=position-1 而不是dr.position=position 因为position就是文件的第一个字节了!
经实践发现,生成Adodb.Stream对象,文件指针位置为0,无论读写文件,都是先将文件指针position+1后再读写字节数据,所以要生成文件前,要将文件指针先-1!
常见的两个错误:
1.当上传文件超过200KB时,报错:“请求对象错误 'ASP 0104 : 80004005' 操作被禁止 /Upload.asp, line 40 ”
因IIS6限制了上传大小为200KB
解决:先将IIS属性中的“允许直接编辑配置数据库”勾选
再找到 XX:\Windows\System32\Inetsrv 中的 metabase.XML, 修改 AspMaxRequestEntityAllowed=204800(200KB)。
2.当文件上传限制已改为200MB后,上传文件大于4MB时,报错:“Response 对象 错误 'ASP 0251 : 80004005'
超过响应缓冲区限制 /showuser.asp,行 0 此 ASP 页的执行造成响应缓冲区超过其配置限制。”
解决办法:找到 XX:\Windows\System32\Inetsrv 中的 metabase.XML, 修改 AspBufferingLimit="4194304"(4MB)。