4.3.5 獲取Server對象的路徑信息
在對存儲在Web網站上的文件進行操作時,需要獲得文件的實際的物理路徑,而不是使用虛擬路徑或URL,盡管在其他網頁中能用它們正常地定位文件。下一章中有一個例子,它使用FileSystemObject對Web站點的InetPub\WWWRoot文件夾中的文件進行讀寫。當創建自己的定制組件或者使用商業化的組件對文件系統進行訪問時,經常需要為其提供一個文件的物理路徑。
Server對象的MapPath方法
可以從Request.ServerVariables集合中提取HTTP報頭變量,它們包含了當前文件的物理路徑(在DOCUMENT_NAME和PATH_TRANSLATED報頭中)。Server對象提供了一個方法MapPath,可以使用這個方法對我們能夠提供一個有效的虛擬路徑的任何文件提取相應的物理路徑。可以在已經使用過的示例網頁中看到使用MapPath方法,並可試驗使用該方法。
如圖4-24所示,在頁面的底部的Miscellaneous Methods部分,有一個按鈕執行Server.MapPath方法,並提供給它靠近該按鈕的文本框中的值。在該網頁的源代碼中已經把這個值設置為“/IIShelp/default.htm”,這個文件應該自動地安裝在計算機上。也可以輸入另一個網頁的URL。
圖4-24 使用Server.MapPath的屏幕
單擊該按鈕重新裝載這個網頁,執行該方法並在頂部顯示結果,在下部顯示原頁面的其余部分,如圖4-25所示:
圖4-25 顯示Server.MapPath的結果
(1) 示例網頁代碼的功能
處理這個過程的代碼是與前面在相似的示例文件中已經使用過的代碼十分相似。
在該頁面頂部的ASP腳本區域中,對單擊的按鈕的名字進行檢查。在這種情況下,該按鈕的名字將是cmdMapPath,簡單地把相匹配的文本框中的值txtMapPath傳送給Server.MapPath方法,並顯示得到的結果:
If Len(Request.Form(“cmdMapPath”)) Then
StrValue = Request.Form(“txtMapPath”)
Response.Write “<B>Results:</B><BR>Server.MapPath (“ & QUOT & strValue _
& QUOT & “ ) returned <B>” & QUOT & Server.MapPath(strValue) _
& QUOT & “</B><HR>”
End If
(2) MapPath和虛擬應用程序目錄
注意,MapPath方法為/IIShelp/default.htm文件獲取的結果在Web服務器目錄外,並在主winnt目錄的help目錄中。這清楚地證明了MapPath方法是非常有用的。
對於在缺省的Web網站目錄中的文件,其URL的路徑部分與物理路徑通常是相同的。例如,一個文件存儲在Web服務器上:
c:\InetPub\WWWRoot\yourfiles\thisfile.ASP
如果安裝時已經在缺省目錄中安裝了的Web根目錄,則URL如下:
http://yoursite.com/yourfiles/thisfile.ASP
然而,IIS Help文件安裝在缺省Web網站目錄外的一個虛擬目錄中,所以用於對其進行訪問的URL和物理路徑之間沒有直接的關聯。只有通過使用Server.MapPath方法才能獲取真實的物理路徑。
4.3..6 使用Server對象格式化數據
當前面討論演示SSI指令的網頁的代碼時,碰巧遇到了使用HTML的一個老問題。在一個HTML網頁中如何顯示HTML代碼?如果“照現在的樣子”使用,也就是在相應的位置上使用所有的HTML字符,會被浏覽器當作Html解釋和執行。這樣當下列內容在浏覽器中顯示時:
This is the syntax of a <TABLE> element:
將不會顯示文本<TABLE>,因為浏覽器將其作為一個數據表的一個開始標記,並照此來執行。為了避免這種情況,必須把在HTML中非法或無效的所有字符轉換到等價的Html字符實體(character entity)。多數常見的字符如表4-5所示:
表4-5 字符與等價的Html實體的關系
字 符
等價的Html實體
字 符
等價的Html實體
<
<
>
>
&
&
“
"
©
©
®
®
所有的實體以&號開始並以分號結束,是在一些語言中表明一個實體的標准方法的一部分,這些語言是基於SGML(標准化常規標識語言)規則的,如Html語言。
1. 數字的Html實體等價字符串
注意最後一個例子,已經注冊的商標®是一個以“#”字符為前綴的數字值,而不是相應含義的一個文本縮寫(如copy對應版權符號©)。具有一個大於126的ANSI代碼值的所有字符在Html中被表示為十進制字符的ANSI代碼,以&#為前綴,以分號為後綴。
事實上,需要留心的是使用數字實體等價字符串要優先於一些較少被支持文本實體字符串。一個例子是商標字符(™),該字符的實體等價字符串為“™”但不是所有浏覽器(例如Navigator)都能識別這個字符串,這種情況下,將在網頁中顯示該實體字符串。相反,使用™在所有浏覽器中都能很好地工作。
2. Server對象的HtmlEncode方法
把HTML轉換為文本是進行有效顯示需要的,否則HTML會被浏覽器當成HTML來對待和執行,這意味著必須對無效的字符進行編碼,使其成為等價的HTML實體字符串。為管理這種轉換,Server對象提供了HtmlEncode方法。可以在本書提供的ASP Server Object示例網頁中練習使用這個方法。
簡單地把一些文本輸入到HTMLEncode對應的文本框中並單擊按鈕。示例中提供了一些真實的Html作為缺省的文本,如圖4-26所示:
圖4-26 使用HtmlEncode方法的屏幕
重新載入該頁面時,在該頁面的頂部顯示結果。HtmlEncode方法把尖括號轉換成了“<”和“>”,而且把雙引號轉換成為“";”,如圖4-27所示:
圖4-27 使用HtmlEncode方法1
(1) 示例網頁代碼的功能
關於得到的結果,有幾個有趣的地方。
首先,在方法名字後面的括號中已經丟掉了<B>和</B>標記,相應增加了一個粗體文本部分。在網頁中顯示原有的值時,<B>和</B>被當成Html提交了,所以<B>和</B>標記消失了,相關內容以粗體文本顯示。
可以十分容易地避免這種情況。事實上,這就是設計HtmlEncode方法的原因。原示例代碼如下:
…
Response.Write “Server.HtmlEncode (“ & QUOT & strValue & QUOT & “) returned”
…
現在所能做的就是把HtmlEncode方法應用於正在輸出的值上:
…
strResult = Server.HtmlEncode(strValue)
Response.Write “Server.HtmlEncode (“ & QUOT & strResult & QUOT & “) returned”
現在輸出了一個十分有用的結果,如圖4-28所示:
圖4-28 使用HtmlEncode方法的結果2
現在已經解決了不提交HTML而顯示HTML的問題。但是如果要在HTML中顯示HTMLEncode方法的結果,而又不提交和處理這些結果,又會發生什麼情況?為了解決這個問題,要從HtmlEncode方法本身考慮:
This is <B>"bold"</B> text
上面的語句在HTML網頁中得不到同樣的顯示結果,這是因為Html字符實體將被浏覽器處理和執行,並顯示為實體所替代的字符。換句話說,得到的是:
This is <B>”bold”</B> text
我們沒有看到實體。為了避免這種情況,可兩次使用Server.HtmlEncode方法。這就把“&”號變換為“&”,這樣就得到了所需的顯示結果。示例網頁的這個部分的代碼是:
If Len(Request.Form(“cmDHtmlEncode”)) Then
strValue = Request.Form(“txtHtmlEncode”) ‘Get the value from the text box
strResult = Server.HTMLEncode(strValue) ‘HtmlEncode to convert <,> and “
strDisplay = Server.HtmlEncode(strResult) ‘Then again to convert & to &
Response.Write “<B>Results:</B><BR>Server.HtmlEncode (“ & QUOT & strResult _
& QUOT & “) returned <B>” & QUOT & strDisplay & QUOT _
& “</B><HR>”
End If
(2) HTMLEncode與Html控件的缺省值
從上面可以看出,如果在一個HTML網頁中要顯示HTML代碼,而又不使之被作為HTML進行處理和執行,HTMLEncode方法是非常有用的。在大多數普通的ASP網頁中不大可能會遇到這種情況,除非使用包含有Html的數據庫或其他數據源中的數據,而又需要作為文本進行顯示。
但是HTMLEncode方法真正有用的地方是,通過設置VALUE屬性預設頁面中文本類型的HTML控件的值。作為例子,可看一下已經用於練習HTMLEncode方法的示例網頁的源程序。創建HTMLEncode對應的文本框的HTML在Html頁中定義如下:
…
<INPUT TYPE=”TEXT” NAME=”txtHtmlEncode” SIZE=”35”
VALUE=”This is <B>"bold"</B> text”>
…
這是“手工編碼”而不是使用Server.HtmlEncode方法。這裡也只關心對雙引號進行編碼而不關心對尖括號的編碼。為什麼?這是因為如果沒有這樣做,該代碼將被讀為:
VALUE=”This is <B>”bold”</B> text”
而在這種情況中尖括號不會帶來問題,未編碼的雙引號則會。在文本框中替換的實際值將是“This is <B>”,即它將在第二個雙引號字符處被截斷。所以,在創建預置控件值的頁面時,應該考慮使用HtmlEncode方法,以避免這些值被截斷:
<%
strValue = Request.Form(“txtSomeValue”)
%>
…
<INPUT TYPE=”TEXT” NAME=”txtSomeValue”
VALUE=”<% = ServerEncode(“strValue”) %>”>
…
當浏覽器發送已經被Html編碼的一個控件的值給服務器時,自動進行反向譯碼。即服務器使用Request集合中原來格式的數據。
3. 格式化UTL的數據
還有另外一種情況,就是經常需要把一個文本字符串變換成能夠在Web網頁中使用的另外一種格式。現代Web服務器和操作系統都十分友好地支持包含空格字符的文件名,但是我們所使用的URL可能包含有空格字符,由於HTTP使用的URL語法不允許有空格字符(和幾個其他字符),可能會出現麻煩。
另外一種更普遍的情況也會出現麻煩。當把這些值作為QueryString集合的成員傳送給服務器時,將被追加到URL的末尾(在一個問號字符之後)。這種情況發生在<FORM>的METHOD屬性被設置為“GET”(或者是省略了METHOD屬性)的情況。換句話說,對於直接追加到URL上的值,都可能出現麻煩。這可能發生在<A>元素中:
<A HREF=http://myserver.com/mypage.ASP?title=Instant JScript>Instant JScript</A>
一些浏覽器(例如Internet Explorer)可以對此進行處理,因為它們在把HTTP請求發送到服務器之前,自動地執行必要的轉換。然而,許多其他的浏覽器不進行這種轉換,並導致了URL通常在第一個空格或非法字符處被截斷。這樣在Navigator中,上面給出的鏈接要求的網頁變為http://myserver.com/mypage.ASP?title=Instant。在服務器上,title名字/值對的丟失部分會使代碼失敗。
考慮到HTTP協議定義的限制,必須從作為HTTP請求中的URL使用的字符串中刪除非法的字符(非法字符是所有那些ANSI代碼在126之上的字符和ANSI代碼在126以下的某些字符)。
ANSI代碼大於126的字符必須用百分號後跟十六進制形式的ANSI代碼進行替換。這樣,版權字符©變成%A9。ANSI代碼在126之下在URL中不合法的字符,同樣使用相應的替代字符串;如表4-6所示:
表4-6 字符與HTTP/URL代替物的關系
字 符
HTTP/URL代替物
字 符
HTTP/URL代替物
空格
+
\
%5C
‘
%27
]
%5D
!
%21
^
%5E
#
%23
`
%60
$
%24
{
%7B
%
%25
|
%7C
&
%26
}
%7D
(
%28
+
%2B
)
%29
<
%3C
/
%2F
=
%3D
:
%3A
>
%3E
;
%3B
Chr(10)
忽略
[[/TD]
%5B
Chr(13) [TD]
%0D
4. Server對象的URLEncode方法
Server對象提供了可以用來把任意字符串轉換成相應的合法HTTP URL的方法。可以利用示例網頁對這個名為URLEncode的方法進行練習,如圖4-29所示:
圖4-29 使用URLEncode方法的屏幕
這裡,輸入的值作為URL是非法的,它包含了空格和ANSI代碼大於126的字符。對這個值,使用URLEncode方法的結果是所有的空格被替換成一個加號,版權符號被替換為 %A9,如圖4-30所示:
圖4-30 使用URLEncode方法的結果
(1) 示例網頁代碼的功能
在示例網頁中,處理這個功能的代碼非常簡單,僅僅檢查是否單擊了URLEncode方法對應的按鈕,如果單擊了,把對應的文本框中的值傳遞給Server.URLEncode方法並顯示結果:
If Len(Request.Form(“cmdURLEncode”)) Then
strValue = Request.Form(“txtURLEncode”)
Response.Write “<B>Results:</B><BR>Server.URLEncode (“ & QUOT & strValue _
& QUOT & “) returned <B>” & QUOT & Server.URLEncode(strValue) _
& QUOT & “</B><HR>”
End If
(2) 對Html元素和其他鏈接使用URLEncode
URLEncode方法更普遍地用於把<A>元素或其他鏈接的值寫到ASP網頁。例如,如果在查詢字符串中建立了一系列的鏈接,這;些鏈接包含來自一個數據庫的值,首先應該對這個字符串使用Server.URLEncode方法:
<%
strValue = Request.Form(“txtSomeValue”)
‘Create the full URL for the link as an HTTP-legal string
strURL = http://mysite.com/books.ASP?title= & Server.URLEncode(“strValue”)
‘Make sure we don’t have any non-legal Html characters in the page text
strLink = Server.HtmlEncode(“strValue”)
%>
…
<A HREF=”<% = strURL %>”><% = strValue %></A>
…
如果放入字符串strValue的值包含標題“Active Server Pages©”,將得到由這個代碼段創建的如下所示的Html:
<A HREF=http://mysite.com/books.ASP?title=Active+Server+Pages%A9>
Active Server Pages©</A>
注意,我們不僅僅使用Server.URLEncode方法來建立一個合法的URL字符串,而且還對鏈接的文本使用了Server.HTMLEncode方法,以確保把所有非法的字符轉換為合適的Html等價實體。
和HtmlEncode方法一樣,不用反譯碼ASP網頁中的URL編碼值。IIS自動地實現URL編碼字符串的轉換,該字符串在HTTP請求中轉換為它們原先格式,使得它們在內置對象中是可用的。
4.4 小結
在這一章中,通過在Web服務器上發生的處理過程,討論了為Web網頁提供動態內容所涉及的一些問題。這些問題的一部分不是直接地與ASP本身相關,但對這些問題的理解,將有助於理解基本的處理工作是如何進行的。
本章介紹了IIS如何支持傳統的服務器端包含指令,有一些指令可能仍然是有用的。特別是,#exec指令對執行系統命令以及集成原有的應用程序都是有用的。同時也討論了一條特別的服務器端包含指令——#include語句,了解了在ASP網頁內部使用這條命令的相關問題。
然而,ASP Server對象占了本章的大部分。它提供了在ASP網頁內管理服務器端處理過程的方法。在Web服務器和ASP的正確的環境中,它可用來創建其他對象、應用程序或組件的實例。它同時也提供了一系列的方法,這些方法允許執行其他的網頁或資源,以及以正確方式格式化信息,以便在ASP腳本和網頁中使用。 Server對象也帶來了一個新的ASP內置對象:ASPError對象,它為腳本提供較好的錯誤處理方法。現在可以提供“正統的”腳本錯誤處理,並獲取有關錯誤的信息。