一、无组件上传的原理
我还是一点一点用一个实例来说明的吧,客户端html如下。要浏览上传附件,我们通过<input type="file">元素,但是一定要注意必须设置form的enctype属性为"multipart/form-data":
<form method="post" action="upload.asp" enctype="multipart/form-data">
<label>
<input type="file" name="file1" />
</label>
<br />
<input type="text" name="filename" value="default filename"/>
<br />
<input type="submit" value="submit"/>
<input type="reset" value="reset"/>
</form>
后台asp程序中,以前获取表单提交的ascii 数据,非常的容易。但是如果需要获取上传的文件,就必须使用request对象的binaryread方法来读取。binaryread方法是对当前输入流进行指定字节数的二进制读取,有点需要注意的是,一旦使用binaryread 方法后,再也不能使用request.form 或 request.querystring 集合了。结合request对象的totalbytes属性,可以将所有表单提交的数据全部变成二进制,不过这些数据都是经过编码的。首先让我们来看看这些数据是如何编码的,有无什么规律可循,编段代码,在代码中我们将binaryread读取的二进制转化为文本,输出出来,在后台的upload.asp中(注意该示例不要上传大文件,否则可能会造成浏览器死掉): <%
dim bidata, postdata
size = request.totalbytes
bidata = request.binaryread(size)
postdata = binarytostring(bidata,size)
response.write "<pre>" & postdata & "</pre>" '使用pre,原样输出格式
' 借助recordset将二进制流转化成文本
function binarytostring(bidata,size)
const adlongvarchar = 201
set rs = createobject("adodb.recordset")
rs.fields.append "mbinary", adlongvarchar, size
rs.open
rs.addnew
rs("mbinary").appendchunk(bidata)
rs.update
binarytostring = rs("mbinary").value
rs.close
end function
%>
简单起见,上传一个最简单的文本文件(g:\homepage.txt,内容为"宝玉:http://www.webuc.net")来试验一下,文本框filename中保留默认值"default filename",提交看看输出结果:
-----------------------------7d429871607fe
content-disposition: form-data; name="file1"; filename="g:\homepage.txt"
content-type: text/plain
宝玉:http://www.webuc.net
-----------------------------7d429871607fe
content-disposition: form-data; name="filename"
default filename
-----------------------------7d429871607fe--
可以看出来对于表单中的项目,是用过"-----------------------------7d429871607fe"这样的边界来分隔成一块一块的,每一块的开始都有一些描述信息,例如:content-disposition: form-data; name="filename",在描述信息中,通过name="filename"可以知道表单项的name。如果有filename="g:\homepage.txt"这样的内容,说明是一个上传的文件,如果是一个上传的文件,那么描述信息会多一行content-type: text/plain来描述文件的content-type。描述信息和主体信息之间是通过换行来分隔的。
基本上清晰了,根据这个规律我们就知道该怎么来分离数据,再对分离的数据进行处理了,不过差点忽略一个问题,就是边界值(上例中的"-----------------------------7d429871607fe")是怎么知道的?每次上传这个边界值是不一样的,还好还好asp中可以通过request.servervariables( "http_content_type")来获之,例如上例中http_content_type内容为:"multipart/form-data; boundary=---------------------------7d429871607fe",有了这个,我们不仅可以判断客户端的form中有无使用enctype="multipart/form-data"(如果没有使用,那么下面就没必要执行啦),还可以获取边界值boundary=---------------------------7d429871607fe。(注意:这里获取的边界值比上面的边界值开头要少"--",最好补充上。)
至于如何分析数据的过程我就不多赘述了,无非就是借助instr,mid等这样的函数来分离出来我们想要的数据。
二、分块上传,记录进度
要实时反映进度条,实质就是要实时知道当前服务器获取了多少数据?再回想一下我们实现上传的过程,我们是通过request.binaryread(request.totalbytes)来实现的,在request的过程中我们无法得知当前服务器获取了多少数据。所以只能通过变通的方法了,如果我们可以将获取的数据分成一块一块的,然后根据已经上传的块数我们就可以算出来当前上传了多大了!也就是说,如果我1k为1块,那么上传1mb的输入流就分成1024块来获取,例如我当前已经获取了100块,那么就表明当前上传了100k。当我提出分块的时候很多人觉得不可思议,因为他们都忽略binaryread方法不仅是可以读取指定大小,而且可以连续读取的。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器