- Login
帳號:
密碼:
ASP MENU
線上教學
   ASP 教學
VB.NET 教學
JSP 教學
JAVA 教學
完整 ASP 教學
程式下載
   ASP 程式下載
提供 ASP 程式
程式量身訂做
   收費標準
填寫需求表
討論交流專區
   程式討論區
電腦資訊交流
工作機會
   社會人就職情報
汎亞人力銀行
大台中人力銀行
大高雄人力銀行
相關連結
   ASP 虛擬空間
ASP 相關網站
聯絡我們
   意見信箱
加入會員程式討論區線上購物回首頁
ASP 教學
用ASP和VBScript上載文件(一)
青蘋果電腦工作室
  從瀏覽器上載文件是從客戶機向服務器傳遞文件的一個簡易方法。從第三代瀏覽器Netscape和 Microsoft起,多數瀏覽器都可以向服務器上載文件,而不需要向用戶提供特殊的訪問方式或軟件。

一些ASP組件是為文件上載而設計的,例如:
Posting Acceptor
( Microsoft SiteServer的一部分),
AspSmartUpload(Advantys),
AspUpload (PersistsSoftware),
SA-FileUpSoftware Artisants)

  本文的開始將告訴你關於創建這類組件的信息,而這些組件通常使用VB、C++或Java。

  這些組件的問題在於它們是第三方產品而非標準ASP的一部分。作為第三方組件,必須在服務器上進行安裝。這就意味著必須在服務器上復制DLL並註冊。大多數的主機系統不允許在他們的服務器上進行這樣的設置,因為有可能發生配置問題(尤其是虛擬主機)。第二個缺點是它們大部分不是免費的,不提供源代碼,也就不能根據需要進行定制。

  因此我需要編寫VBScript代碼來解決文件上載的問題。這不是一個必然的選擇,因為VBScript是一種腳本語言,只能使用variants數據類型,並且不能提供許多管理二進制數據和字節數組的內置函數。

  要理解上載的過程,首先要知道數據用HTTP協議從瀏覽器發送到服務器的方式。這就意味著要理解“ multipart/form-data” (多部分/格式-數據)的表單提交。

上載表單

  通常情況下,使用HTML表單從瀏覽器向服務器傳遞數據。這個表單中可能包含文本域、檢驗框、按鈕以及上載文件的文件類型控制。使用者用自己的數據填充並將這個表提交給服務器。

  表單元素中的 enctype 屬性規定了傳遞給服務器的表數據集編碼的內容類型。enctype 屬性的默認值是“application/x-www-form-urlencoded”,但當向服務器傳送大量文本、包含非ASCII字符或二進制數的數據時,這個默認類型就不能勝任了。這時,文件上載提交表單時應使用“multipart/form-data”內容類型。

  一個“multipart/form-data”信息包含一系列部件,每個部件都可能包含:
一個Content-Disposition(內容-處理)頭,其值為"form-data" ;一個規定控制名的name(名稱)屬性。

  對於一個文件類型控制,一個部件可能包含更多信息:
在客戶機上規定原始路徑和文件名的filename(文件名)屬性;所發送的二進制數據控制的Content-Type (內容-類型)頭。

  在這些頭的後面跟隨著控制的二進制或文本內容。

  以下例子說明“multipart/form-data”的編碼,客戶機的瀏覽器應有這個表單:

如果這個表單被提交,在服務器上可讀到這些請求:

-----------------------------7cf87224d2020a
Content-Disposition: form-data; name="email"
PhCollignon@email.com
-----------------------------7cf87224d2020a
Content-Disposition: form-data; name="blob"; filename="c:\image.gif"
Content-Type: image/pjpeg

-----------------------------7cf87224d2020a
Content-Disposition: form-data; name="Enter"
Submit Query
-----------------------------7cf87224d2020a--

  當那個內容作為響應被傳送回客戶機時就會被顯示出來。應該用Request.binaryRead 和Response.binaryWrite 方法讀和寫二進制數據。

〈%
Response.BinaryWrite(Request.BinaryRead(Request.TotalBytes))
%〉

可以看到響應的各部分用分界線來劃分:
-----------------------------7cf87224d2020a
最後一個分界線後面跟隨的是’ -- ’ 。

  每一個控制都有一個Content-Disposition 。name屬性識別由HTML表發送的控制(email、blob和Enter)。 對於一個文件類型控制(blob),
文件名也是Content-Disposition 頭的一部分,Content-Type 頭給出二進制 數據的內容類型。

上載腳本

  上面所有內容都必須經過分解。在VB 或 C++中, 這非常明顯,因為為此提供了許多對象和方法。在VBScript 中,必須使用語言所提供的一些函數,並要解決VBScript中使用的雙字節編碼的變量字符串的問題。

VBScript函數

  原始數據是二進制格式,所以必須使用專為管理二進制數據而設計的VBScript函數。因為我們將原始數據作為一個字節的字符串來考慮, 所以 MidB、InstrB 和 LenB 函數就有用了。 但是要避免VBScript的classic字符串,因為它們是雙字節編碼的字符串,不適宜分解成單字節。

  這些是VBScript函數中僅有的用來分解字節的函數。還需要一個方法,從被分解的數據中得到雙字節編碼的字符串,這樣就可以使用VBScript編碼中的字符串了。為了在InstrB中把字符串作為一個自變量使用,還需要一個函數,把雙字節字符串轉換成單字節字符串。

  為了我寫了兩個函數,getString() 和 getByteString(),稍後再對此進行解釋。

結構

  分解的數據被存儲在VBScript Dictionary 對象中。 Dictionary 對象是hash 表對象,它存儲(key, item)對。它是VBScript和ASP2.0的一部分。

  定義第一個Dictionary 對象 " UploadRequest " 。這個對象包含由上載表提交的所有控制。Key是控制的名字,Item則是對象中所包含的控制的信息:
"ControlName1", Dictionary control1
"ControlName2", Dictionary control2

  代表一個控制的Dictionary 對象包含著下面的(key, item) 對:
"Value", String or binary content
"FileName", Name of uploaded file
"ContentType", ContentType of uploaded file

  把這些結合起來,就有以下例子:

UploadRequest : "email", UploadControl 1 : "Value", PhCollignon@email.com
"blob" , UploadControl 2 : "filename", C:/image/file.gif "ContentType" :
image/gif "Value" : GIF89ai?
這個對象對於以後存取和使用數據非常有用。

分解

  這堿O分解、讀和記錄上載控制的代碼。這個過程用"BuildUploadRequest"程序來完成,這個程序只有一個自變量,就是原始二進制數據RequestBin。

Sub BuildUploadRequest(RequestBin)

  首先要找到分界線,通過分界線可以知道控制循環何時結束。

’Get the boundary PosBeg = 1 PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
boundary = MidB(RequestBin,PosBeg,PosEnd-PosBeg) boundaryPos = InstrB(1,RequestBin,boundary)

  有一個問題是InstrB需要單字節字符串作為自變量。為此寫了一個函數:getByteString(String) ,此方法可以把VBScript的雙字節字符串轉換成單字節字符串。在代碼解釋的最後再描述這個函數。

在找到結束分界線之前進行下列循環:
’Get all data inside the boundaries
Do until (boundaryPos=InstrB(RequestBin,boundary & getByteString("--")))

  循環中的每一步都處理一個控制。有關這一控制的所有數據都保存在dictionary對象中。每一個循環創建一個新的dictionary對象UploadControl。

’Members variable of objects are put in a dictionary object Dim UploadControl
Set UploadControl = CreateObject("Scripting.Dictionary")

  首先從" Content-Disposition " 頭中找到控制的名字。名字的結尾用"字符或chr(34)劃分。
’Get an object name Pos = InstrB(BoundaryPos,RequestBin,getByteString("Content-Disposition"))
Pos = InstrB(Pos,RequestBin,getByteString("name=")) PosBeg = Pos+6 PosEnd
= InstrB(PosBeg,RequestBin,getByteString(chr(34))) Name = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

  現在測試控制是文件類控制還是文本類控制。如果是文本類控制,除了它的名字以外沒有其它任何數據。 如果是文件類控制,就會得到一些額外信息,如文件名和Content-Type。

PosFile=InstrB(BoundaryPos,RequestBin,getByteString("filename=")) PosBound
= InstrB(PosEnd,RequestBin,boundary) ’Test if object is of file type If
PosFile〈〉0 AND (PosFile〈PosBound)

  Then 如果是控制是文件類控制,就將路徑和文件名進行分解,並將他們填加到控制的dictionary 對象中。分解後的文件名是一個單字節字符串,要將它轉換成雙字節字符串才能作為variant字符串變量使用。這通過最後定義的getString()方法來實現:

’Get Filename, content-type and content of file PosBeg = PosFile + 10 PosEnd
= InstrB(PosBeg,RequestBin,getByteString(chr(34))) FileName = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
’Add filename to dictionary object UploadControl.Add "FileName", FileName
Pos = InstrB(PosEnd,RequestBin,getByteString("Content-Type:")) PosBeg =
Pos+14 PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13))) ’Add content-type
to dictionary object ContentType = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))

  UploadControl.Add "ContentType",ContentType 現在就可以得到文件的核心內容了。這個內容不需要轉換,因為它是二進制的。可以將它存入一個文件系統或作為一個二進制長對象(blob)放入數據庫中。

’Get content of object PosBeg = PosEnd+4 PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
Value = MidB(RequestBin,PosBeg,PosEnd-PosBeg)

  Else 如果是文本類控制,除了內容以外就沒有其它數據需要分解。內容要轉換成為雙字節字符串,以便將來用 在VBScript代碼中。

’Get content of object Pos = InstrB(Pos,RequestBin,getByteString(chr(13)))
PosBeg = Pos+4 PosEnd = InstrB(PosBeg,RequestBin,boundary)-2 Value = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
End If

  將內容加入dictionary對象中。將key設置成 " Value ",那麼item 就是內容。根據控制類型的不同,內容可以是字符串或二進制數據。

’Add content to dictionary object
UploadControl.Add "Value" , Value

  最後將控制的dictionary 對象加入一個全程dictionary 對象中。使用的key 是控制的名字。item 是剛剛創建的dictionary對象,名為UploadControl。

’Add dictionary object to main dictionary UploadRequest.Add name, UploadControl
’Loop to next object BoundaryPos=InstrB(BoundaryPos+LenB(boundary),RequestBin,boundary)
Loop End Sub

字節-字符串轉換函數

下面是將雙字節字符串轉換成單字節字符串的函數。

’Byte string to string conversion Function getString(StringBin) getString
="" For intCount = 1 to LenB(StringBin) getString = getString & chr(AscB(MidB(StringBin,intCount,1)))
Next End Function 下面是將字符串轉換成單字節字符串的函數,它用來格式化InstrB函數的自變量。

’String to byte string conversion Function getByteString(StringStr) For
i = 1 to Len(StringStr) char = Mid(StringStr,i,1) getByteString = getByteString
& chrB(AscB(char)) Next End Function




頂端
本網頁最佳瀏覽模式為:瀏覽器 IE4.0 以上    解析度: 800 x 600
Copyright © 2000-2020 COOLASP All Rights Reserved