最近在单位做的一个项目里需要有文件上传的功能,正好手头一本书的附赠光盘里有一个上传组件,心中大喜。可惜随之便发现这是一个试用版,不给钱就只能用50次,太小气了!!好在头头催得不紧,时间充裕,干脆自己试着做一个,既可长经验值,又能长成就感,不试白不试!以下介绍的便是俺折腾了两天半捣鼓出来的一个只能说是雏形的玩意,区区三十行代码,大侠们不要笑俺哦,这只是写给与俺一样好奇心强但经验值低的弟兄们看的。
文件上载所需的第一步当然是进入一个有“file”表单元素的页面,具体就不说了,大家都知道。但是若想做一个能够接受该文件并且将其保存到服务器硬盘上的组件,必须知道所提交的原始数据的怎么一个模样才行。做到这一点并不难:
<%
Dim FormData,FormSize
FormSize=Request.TotalBytes
FormData=Request.BinaryRead(FormSize)
Response.BinaryWrite FormData
%>
因为需要读取的是前一个页面提交来的原始字节数据,因此不能使用Request.Form()方法,必须使用BinaryRead方法,并且一旦使用了这个方法,就不能再在同一个页面中使用Form()方法了,反之亦然。基于同样的道理,向页面输出时也必须使用BinaryWrite方法,不过这并不妨碍你继续使用Response.Write方法。
在下面的描述中假设浏览者选择上传的文件是一个GIF图片,你会发现这段代码运行的结果并不是在浏览器上显示出这幅图片,而只是输出了一堆基本上是乱七八糟的字符:
-----------------------------7ce20d227c0232
Content-Disposition: form-data; name="file"; filename="C:\mypic.gif?http://www.xvna.com"
Content-Type: image/gif
GIF89a 垐??!?倇挌7昳€聉}$挝顿藶排湃缺哪浇爬⒖咯技Φ档北发创熍皗獂勃姰畾棩ゥ挝顿藶排湃缺哪浇爬⒖咯技Φ档北发创熍皗獂勃姰畾棩ゥゥ挗|櫃櫇潒櫃嚈櫃殦x敂儘崓潅倢寍檱Z杹r?杽Z剟剠厁儍t??p{{{zzszzlsss媙arrj僯jrre€ccfff乨Xfffddjj^fffddZ__UZZZYYSWWMRRRRRJ_BBKKK?IIB? ??W::AAA?S;?-----------------------------7ce20d227c0232--
不奇怪,这就对了!因为原始数据并不仅仅是图片文件本身的数据,它还包含有对该文件在用户硬盘上的路径、类型、提交页面的表单域名等相关信息的描述,以及头尾两段基本相同的标识(即“-----------------------------7ce20d227c0232”),我想这对标识应该是在表单中含有多个元素时起分割作用的。中间的那段数据,即以“GIF89a”开头,直到最后一个“;”,才是我们所想得到的GIF图片文件的数据。若想让浏览器能够显示出这幅图片,当然得先把这些不需要的内容去掉再向页面输出。因此下面该做些什么就很明了了。
第一步,掐头:
“头”与图片数据的分界线就是两对回车换行符(在浏览器中是看不到“GIF89a”之前的那个空白行的,得把输出结果粘贴到写字板里去研究,记事本也不行)。
Dim DataStart,CLStr
CLStr=ChrB(13) & ChrB(10)
DataStart=InStrB(FormData,CLStr & CLStr)+4
其中的4是两对回车换行符的长度,另外要注意这里都是在针对字节数据进行操作,而不是字符,因此不要用错了函数,少敲了个“B”就完全得不到正确结果了。
第二步,去尾:
“头”有多大算是搞清了,那尾呢?不急,先获取开头那段标识的具体内容,注意它的结尾处是一对回车换行符:
Dim DivStr
DivStr=LeftB(FormData,InStrB(FormData,CLStr)-1)
因为我们将要使用MidB方法截取图片数据,所以接下来需要搞清楚整段图片数据的字节数,就用前面已定义了的DataSize变量:
DataSize=InStrB(DataStart+1,FormData,DivStr)-DataStart-2
为什么要减2呢?因为末尾那段标识之前也有一对回车换行符。至此,图片数据便可以很轻易地得到并在浏览器上输出了:
FormData=MidB(FormData,DataStart,DataSize)
Response.BinaryWrite FormData
不过我想你一定不会满足于到此为止的,因为还没有存盘呢!当然我也不会做到这里便收工,否则是没法向头头交差的。前面所探讨的这些内容都还只局限在纯粹的ASP脚本程序范围内,并没有涉及到组件技术。其实我一开始并没有想向这方面努力,只想靠ASP解决问题,可惜FileSystemObject没告诉我它可以往硬盘上写二进制文件,在这个论坛上问了半天也没人睬我,只好自己动手编组件了。
不过接下来的过程并不像想象中的那样艰难。
所要做的这个组件的功能很简单,只提供了一个方法:SaveFile(Pathname),在这个方法内,程序首先获取上传页面所提交的文件的字节数据,就象前文所述的脚本程序一样,然后再将这些数据写到服务器硬盘上由参数Pathname所指定的一个二进制文件内,一切便大功告成了,至于如何使这个组件进一步完善些,呵呵,以后慢慢来吧。
具体怎么做呢?打开VB,然后请听下回分解。