文件上載所需的第一步當然是進入一個有“file”表單元素的頁面,具體就不說了,大家都知道。但是若想做一個能夠接受該文件并且將其保存到服務器硬盤上的組件,必須知道所提交的原始數據的怎么一個模樣才行。做到這一點并不難:
$#@60;%
Dim FormData,FormSize
FormSize=Request.TotalBytes
FormData=Request.BinaryRead(FormSize)
Response.BinaryWrite FormData
%$#@62;
因為需要讀取的是前一個頁面提交來的原始字節數據,因此不能使用Request.Form()方法,必須使用BinaryRead方法,并且一旦使用了這個方法,就不能再在同一個頁面中使用Form()方法了,反之亦然。基于同樣的道理,向頁面輸出時也必須使用BinaryWrite方法,不過這并不妨礙你繼續使用Response.Write方法。
在下面的描述中假設瀏覽者選擇上傳的文件是一個GIF圖片,你會發現這段代碼運行的結果并不是在瀏覽器上顯示出這幅圖片,而只是輸出了一堆基本上是亂七八糟的字符:
-----------------------------7ce20d227c0232Content-Disposition: form-data; name="file"; filename="C:mypic.gif"Content-Type: image/gif
GIF89a ???!???7??v}$撾頓?排湃缺哪?澆爬⒖咯技Φ檔北?發創?????勃????ゥ撾頓?排湃缺哪?澆爬⒖咯技Φ檔北?發創?????勃????ゥゥ???|???????x???????Z?r??Z????t??p{{{zzszzlsss?arrj?jrre?cfff?Xfffddjj^fffddZ__UZZZYYSWWMRRRRRJ_BBKKK?IIB? ??W::AAA?S;?-----------------------------7ce20d227c0232--
不奇怪,這就對了!因為原始數據并不僅僅是圖片文件本身的數據,它還包含有對該文件在用戶硬盤上的路徑、類型、提交頁面的表單域名等相關信息的描述,以及頭尾兩段基本相同的標識(即“-----------------------------7c d227c0232”),我想這對標識應該是在表單中含有多個元素時起分割作用的。中間的那段數據,即以“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,然后請聽下回分解。