<Form action=upload.asp method=post enctype=multipart/form-data>
上傳檔案:<Input type=file name=file1><br>
<input type=submit name=upload value=上傳>
</form>
其中,enctype參數用來設定表單的MIME編碼方式,在進行檔案(或同時包含文字方塊)上傳時,必須將其屬性設定為multipart/form-data;upload.asp是伺服器端對接收到的二進位檔案流進行處理的ASP程序,在本文的後面將陸續介紹其內容。
2.上傳文件格式分析
在處理文件之前,我們要先了解上傳的文件的具體格式,透過編寫下面一段簡單的ASP程式就可以查看其二進位程式碼:
<%
filesize=Request.TotalBytes '取得上傳檔案的大小
filedata=Request.BinaryRead(filesize) '取得上傳檔案的二進位數據
Response.BinaryWrite filedata '在瀏覽器上顯示二進位數據
%>
分析瀏覽器上顯示的上傳文件的二進位代碼,發現代碼包括四個部分(若同時上傳多個文件或文字框,則代碼按上傳的先後次序排列,格式相同),每一部分的內容是用回車換行符號來進行分隔的:
1)第一部分(起始標誌)
-----------------------------7d329631b04d4
2)第二部分(文件說明)
Content-Disposition: form-data; name=file1; filename=C:/Documents and Settings/Administrator/My Documents/Invitation.doc Content-Type: application/msword
在此,我們可以獲得上傳檔案的檔案名稱及絕對路徑,也可以獲得檔案類型。這些資訊是正確保存文件所不可缺少的。
3)第三部分(文件內容)
即文件的二進位內容,略。
4)第四部分(結束標誌)
-----------------------------7d329631b04d4
結合第一部和第四部的內容來看,-----------------------------7d329631b04d4(每次上傳,數值都不一樣)起到了分割符的作用,它標誌著一段資料(當有多個上傳內容時)的開始和結束。從保存檔案所需的資訊來講,我們首先需要從第二部分資料的filename中取得檔案名稱,然後需要正確定位檔案的起始位置,最後利用ASP技術將二進位檔案用本來的檔案名稱儲存即可。若同時上傳多個內容(如多個文字方塊和文件),也是以同樣的方法處理,每部分的內容都包含在分割符之中,只是文字方塊和檔案的表現形式稍有不同,這可以透過具體分析其二進位代碼來了解。
3.利用ASP技術實現文件存儲
上傳文件程式碼的處理
1) 取得分割符代碼
從上面的分析我們已經知道,分割符起到了分割多個資料段(包括文字框和各種類型的文件)的重要作用。前面已經分析過,分割符號出現在第一個回車換行符號前。因此,透過下面這段程式就可獲得分割符代碼:
<%
newline=chrB(13) & chrB(10) 'newline表示二進位的回車符
filesize=Request.TotalBytes 'filesize是上傳檔案的大小
filedata=Request.BinaryRead(filesize) 'filedata是上傳檔案的二進位數據
divider=leftB(filedata,clng(instrb(filedata,newline))-1) 'divider是分割符
%>
註:因為這裡處理的都是二進位字節碼,因此,所有的函數都是使用它的二進位版本,加了b 。
2) 取得文件(或文字方塊)內容
(1) 預備函數(將二進位字串轉換成字串)
上傳檔案的內容不需要經過二進位向字串的轉換過程,直接儲存就可。但是,若需擷取文字方塊內容或檔案的名稱,就必須進行轉換。因此,需要編寫一個通用的,並且適用於漢字的轉換函數。以下是該函數程式碼:
Function BtoS (bstr)
If not Is Null (bstr) Then
for i = 0 to lenb(bstr) - 1
bchr = midb(bstr,i+1,1)
If ascb(bchr)>127 Then '漢字是雙字節,得兩個字元一起處理
temp = temp&chr(ascw(midb(bstr, i+2, 1)&bchr))
i = i+1
Else
temp = temp&chr(ascb(bchr))
End If
next
End If
BtoS = temp
End Function
(2) 取得文件(或文字方塊)內容
在實際的WEB應用程式中,上傳操作可能涉及多項內容,如多個文字方塊、多個檔案等等。文件和文字框很好區分,文件的資料包含了filename=字符串。因此,我們寫瞭如下的通用函數,既可用於提取文件內容,又可提取文字框內容(需進行二進位轉換):
Function getdata(byval data, byval divider, final) 'data表示二進位串;divider表示分割符;final表示資料的結束位置
filename=chrb(102)&chrb(105)&chrb(108)&chrb(101)&chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) 'filename=的二進位表示
bncrlf=chrb(13)&chrb(10) '二進位的回車符
startpos = instrb(data,divider)+lenb(divider)+lenb(bncrlf) ' 開始位置
endpos = instrb(startpos,data, divider)-lenb(bncrlf) '結束位置
part1 = midb(data, startpos, endpos-startpos) '兩個分割符之間的內容
firstline = midb(part1, 1, instrb(part1, bncrlf)-1) ' 內容之前的說明段
If (instrb(firstline,filename)=0) Then '若為文字框,取得文字方塊字串內容
stemp=midb(part1,instrb(part1,bncrlf&bncrlf)+lenb(bncrlf&bncrlf),lenb(part1)-instrb(part1,bncrlf&bncrlf)+lenb(bncrlf&bncrlf))
getdata=BtoS(stemp)
Else '若為文件,取得文件二進位內容
Getdata=midb (part1, instrb (part1, bncrlf&bncrlf)+lenb (bncrlf&bncrlf), lenb (part1)
-instrb(part1,bncrlf&bncrlf)+lenb(bncrlf&bncrlf))
End If
Final=endpos
End function
在程式中直接呼叫函數就可取得所需文件(或文字方塊)內容,如下所示:
<%
Content=getdata (data, divider, position)
%>
3) 取得檔案名稱
前面已經分析過了,上傳檔案資料流的filename=欄位包含了檔案的名稱和絕對路徑。一般來說,我們只需提取出路徑中的檔案名稱即可,以下是程式碼:
<%
namepos=instrrev(B2S(firstline),chr(92)) 'firstline即上述的說明部分數據,chr(92)
表示/
filename=midb(firstline,namepos+1,lenb(firstline)-namepos-1) '取得檔案名稱
%>
利用ASP直接實現檔案上傳功能
傳統的ASP程式設計師只能利用FILESYSTEMOBJECT物件對文字檔案(.txt)進行移動、複製、刪除等操作,若需處理二進位對象,則不得不採用本文前面介紹的那些方法來實現。但是,現在ASP中的ADO.STREAM物件可以同時操作文字物件和二進位物件(可以在http://www.microsoft.com/data下載),利用它就可以在ASP中直接實作檔案上傳功能。下面,我們就介紹其實作過程。
1)開啟STREAM對象
對於SREAM物件而言,若要進行文件的保存,則必須是將該物件的全部內容進行保存。因此,我們必須要建立兩個(或多個)STREAM對象,其中一個為來源資料流,即接收初始的二進位資料;另一個為目的資料流,即接收來自經來源資料流處理後的數據,並最終儲存為所需的文件。
<%
set str=server.CreateObject(ADODB.Stream) 'str為來源資料流
str.Mode=3 '設定開啟模式,3為可讀可寫
str.Type=1 '設定資料類型,1為二進位數據
str.Open
set desc=server.CreateObject(ADODB.Stream) 'desc為目標資料流
desc.Mode=3
Desc.Type=1
desc.Open
%>
2)STEAM物件間內容的複製
在該部分,必須在來源資料流中定位文件開始的位置,並且求出文件內容的長度,才能將文件正確的複製到目的資料流中,並且保存文件,程式碼如下:
<%
formdata=Request.BinaryRead(Request.TotalBytes) 'formdata為上傳的所有內容
str.Write formdata ' 賦值來源資料流
str.position=count-lenb(result)-2 'position指出檔案的起始位置
str.copyto desc, lenb(filecotent) 'lenb(filecontent)表示檔案的長度
desc.SaveToFile fullpath,2 '以fullpath指定的路徑及名稱儲存文件
%>
3)關閉STEAM對象
編程完成後,應關閉並釋放STEAM對象,如下所示:
<%
Desc. Close
Set desc=nothing
Str. Close
Set STR=nothing
%>
總結
本文給出了利用ASP直接實現文件上傳的方法,在本單位自行開發的資訊管理系統中得到了很好的應用。實務證明:與傳統的幾種文件上傳方法相比,此方法更簡單、更有效率。