摘要:在基於瀏覽器/伺服器的應用程式環境中,在瀏覽器中上傳各種類型的檔案一直是困擾使用者檔案管理應用程式的難題之一。在HTTP中上傳檔案有三種機制:RFC1867,PUT和WebDAV。常用的實作方法是利用在RFC1867中引入的一個新類型:File以及ADO Stream物件。本文對上述上傳方法及實作原理作了論述,並給出了具體解決實例。
關鍵字:ASP 元件FILE物件
目前,基於瀏覽器/伺服器模式的應用程式比較流行。當使用者需要將檔案傳輸到伺服器上時,常用方法之一是執行FTP伺服器並將每個使用者的FTP預設目錄設為使用者的Web主目錄,這樣使用者就能執行FTP客戶程式並上傳檔案到指定的Web目錄。這就要求使用者必須懂得如何使用FTP客戶程式。因此,這種解決方案僅對熟悉FTP且富有經驗的使用者來說是可行的。 如果我們能把文件上傳功能與Web集成,使用戶僅用網頁瀏覽器就能完成上傳任務,這對他們來說將是非常方便的。但是,一直以來,由於File System Object的僅能傳送文字檔案的限制,所以ASP最大的難題就是檔案上傳問題。以下介紹的就是如何在基於HTTP協定的網頁中實作檔案的上傳。
一.透過HTTP上傳的三種機制
透過HTTP上傳有三種機制:RFC1867, PUT 和WebDAV。
PUT 是在HTTP 1.1引入了新的HTTP動詞。當web伺服器收到一個HTTP PUT和物件名字,它將會驗證用戶,接收HTTP流的內容,並把它直接存入web伺服器。由於這可能會對一個web站點造成破壞,並且還會失去HTTP最大的優勢:伺服器可編程性。在PUT的情況下,伺服器自己處理請求:沒有空間讓CGI或ASP應用程式介入。唯一讓你的應用程式捕捉PUT的方法是在低層操作,ISAPI過濾層。由於相應的原因,PUT的應用很有限。
而WebDAV允許web內容的分散式認證與翻譯。它引入了幾種新的HTTP動詞,允許透過HTTP上傳,鎖定/解鎖,登記/檢驗web內容。 Office 2000中的"Save to web" 是透過WebDAV來實現的。如果你所感興趣的一切都是上傳內容,WebDAV應用得非常出色,它解決了許多問題。 然而,如果你需要在你的web應用程式裡面上傳文件,WebDAV對你就毫無用處可言。像HTTP PUT一樣,那些WebDAV的動詞是被伺服器解釋的,而不是web應用程式。你需要工作在ISAPI過濾層來存取WebDAV的這些動詞,並在你的應用程式中解釋內容。
RFC1867 ( http://www.ietf.org/rfc/rfc1867.txt ) 最後被W3C在HTML3.2中接受前,是作為一種建議標準。它是一種非常簡單但是功能很強大的想法:在表單欄位中定義一個新類型。
<INPUT TYPE="FILE">
並且在表單本身加入了不同的編碼方案,不再使用典型的:
<FORM ACTION="formproc.asp" METHOD="POST">
而是使用:
<FORM ACTION="formproc .asp" METHOD="POST" ENCTYPE="multipart/form-data">
這種編碼方案在傳送大量資料的時候,比起缺省的"application/x-url-encoded"表單編碼方案,顯得效率要高得多。 URL編碼只有很有限的字符集,使用任何超出字符集的字符,必須用'%nn'代替,這裡的nn表示相應的2個十六進制數字。例如,即使是普通的空格字元也要用'%20'來代替。而RFC1867使用多部分MIME編碼,就像通常在e-mail訊息中看到的那樣,不編碼來傳送大量數據,而只是在數據周圍加上很少的簡單但實用的頭部。主要瀏覽器的廠商都採用了建議的"瀏覽..."按鈕,用戶能輕鬆的使用本地"開啟檔案..." 對話方塊選擇要上傳的檔案。
RFC1867仍然將大多數檔案上傳的靈活方法留給了你的web應用程式。 PUT用得很有限。 WebDAV對內容的作者很有用,例如FrontPage用戶,但對想在web應用程式中加入文件上傳的web開發者來說很少用到。因此,RFC1867是在web應用程式中加入檔案上傳的最好的方法。
在實際應用中,微軟免費提供了Posting Acceptor 。 ASP不懂"multipart/form-data" 編碼方案。取而代之,微軟提供了Posting Acceptor ,Posting Acceptor是一種在上傳完成後,接受REPOST到一個ASP頁的ISAPI應用程式。
Software Artisans的SA-FileUp是最早的商業Active Server元件之一。幾經改進,現在作為一個純粹的ASP組件存在。
二.基於ASP的檔案上傳實作原理分析
基本原理是:採用ADO Stream物件的BinaryRead方法將FORM中的所有資料讀出,從中截取出所需的檔案數據,以二進位檔案方式存檔。
以下是上傳檔案頁面的一個範例(upload.htm):
<html>
<body>
<form name="Upload" Method="Post" Enctype="multipart/form-data" Action="Upload.asp">
<input type="file" name="FileName">
<INPUT TYPE="Submit" VALUE="Upload"></TD>
</form>
</body>
</html>
程式中使用了檔案對象,這樣在Upload.asp中採用BinaryRead方法讀來的原始資料就不僅僅是選擇的檔案本身的數據,還包含該檔案在使用者硬碟上的路徑、類型、提交頁面的表單網域等相關資訊的描述,這樣我們就需從中提取出文件的具體內容。根據分析,數據的頭部資訊與數據的分界線是兩對回車換行符,尾部也有分隔信息,我們可以採用類似以下的方法獲取文件數據。
Dim FormData.FormSize,DataStart,CLStr,DivStr
FormSize=Request.TotalBytes
FormData=Request.BinaryRead(FormSize)
CLStr=ChrB(13)&ChrB(10)
DataStart=InStrB(FormData.CLStr&CLStr)+4
'4是兩對回車換行符的長度
DivStr=LeftB(FormData,InStrB(FormData,CLStr)-1)
DataSize=InStrB(DataStart+1,FormData,DivStr)-DataStart-2
FormData=MidB(FormData,DataStart,DataSize)
FormData就是文件的內容了。
中間根據需要,可進行相應的處理。最後的工作就是將文件儲存了。保存的方法可以有兩種:一種是利用VB或VC之類程式中的二進位檔案操作方法,在工程中加入適當的類型庫,最後編譯成DLL文件,使用時再將該DLL檔註冊就可以了。檔案存貯程序如下:
Public Function SaveFile(Pathname As String) As String
Dim objContext As ObjectContext
Dim objRequest As Request
Set objContext=GetObjectContext()
Set objRequest=objContext("Request")
'以下的一段程式碼是進行文件存貯的相關操作Dim FormData() As Byte,CLStr,DivStr
Dim DataStart As Long,DataSize As Long
DataSize=objRequest.TotalBytes
Redim FormData(DataSize-1)
FormData=objRequest.BinaryRead(DataSize)
CLStr=ChrB(13) & ChrB(10)
DataStart=InStrB(FormData,CLStr & CLStr)+4
DivStr=LeftB(FormData,InStrB(FormData,CLStr)-1)
DataSize=InStrB(DataStart+1,FormData,DivStr)-DataStart-2
FormData=MidB(FormData,DataStart,DataSize)
'建立一個二進位檔案並將FormData寫入其中Open Pathname For Binary As 1
Put #1,,FormData
Close #1
SaveFile="OK!"
End Function
第二種方法是利用ADO STREAM提供的二進位檔案操作方法來完成,儲存檔案的語句是: StreamOBJ.SaveToFile (fileName,2)。在這個操作中,我們可以將相關的操作存放在一個類別文件中,在應用時,直接將該類別文件包含在ASP程式中就可以了。具體處理方法,請參閱有關介紹。
三.文件上傳實作方法實例實作檔案
上傳可使用元件或無元件方式。對於元件類,比如說microsoft posting acceptor(簡稱mpa),就是微軟公司發布的一個免費伺服器元件,這類元件的安裝也比較方便。對於微軟的mpa,運行它的安裝檔就可以了。而一般的dll組件形式的,我們則需要進行註冊。例如,要使用aspcnUP.dll,只要在Window 2000上執行regsvr32 [path]aspcnUP.dll,系統出現註冊成功的資訊提示就可以使用該組件了;對於無組件類,如www.5xsoft.com的無元件上傳類別-upload_5xsoft。使用時,只要在處理程序中包含以下的語句就可以了:
<!--#include FILE="upload.inc"-->
set upload=new upload_5xSoft '建立上傳物件
相關的屬性與操作方法,請參閱該元件的使用手冊。
以下是以aspcnUP.dll元件為例,上傳部分類型檔案的原始碼(upload.asp):
<% @ language="vbscript"
Set fileUP=Server.CreateObject("aspcn.Upload")
fileUP.Maxsize=200000
fileUP.Path="d:upfile"
fileUP.Upload
For i=0 to fileUP.Count
fieldname=fileUP.FieldName(i)
If fileUP.FileType(fieldname)="zip" Or ileUP.FileType(fieldname)="rar" Then
fileUP.Save fieldname
End If
Next
Set fileUP=Nothing
%>
四.結束語
瀏覽器/伺服器應用模式還在快速發展著,在微軟新推出的ASP. NET中,已經內建了檔案上傳的功能,使用非常簡單方便。作為一種全新的技術,ASP. NET不只是ASP的簡單升級,它是一個用於Web開發的全新框架,其中包含了許多新的功能。 ASP. NET提供了更易於編寫、結構更清晰的程式碼,利用這些程式碼我們將會更容易進行再利用和分享,從而開發出更多更實用的程式。