|
陶國強(qiáng)
互聯(lián)網(wǎng)傳輸控件(ITC)是一個(gè)很不錯(cuò)的控件,我們可以利用它非常方便地檢索Web資源,但不幸的是,該控件并沒有提供跟蹤數(shù)據(jù)傳輸過程的方法。如果ITC控件具有諸如DownloadProgress或者DataArrival這樣的事件,而且該事件還具有相應(yīng)的參數(shù)就好了,但可惜也沒有。那么有沒有方法來獲取網(wǎng)頁下載過程的信息呢?答案是肯定的,下面就來討論一下如何獲取HTTP數(shù)據(jù)傳輸?shù)倪^程信息。 通常,我們使用ITC控件提供的兩種方法來下載Web頁面,即OpenURL和Execute,其中,OpenURL方法最簡單,但其功能有限,用這種方法并不能得到任何過程信息。為了用OpenURL方法獲取Web頁面內(nèi)容,我們可以使用下面的代碼: strPageContent = Inet1.OpenURL(strURL, icString) 可見,用OpenURL方法下載頁面確實(shí)很簡單,但我們不能對(duì)到達(dá)的數(shù)據(jù)進(jìn)行控制,所以,我們需要訪問Winsock緩沖區(qū),該緩沖區(qū)的功能是存儲(chǔ)到達(dá)的數(shù)據(jù)。如果我們能夠訪問緩沖區(qū)內(nèi)的數(shù)據(jù),那么我們就能在傳輸過程中的任何時(shí)刻計(jì)算出已到達(dá)數(shù)據(jù)的大小。而利用ITC控件的Execute方法,情況就完全不同了,下面我們來看一下該方法是如何工作的: 'Execute方法只是向Web服務(wù)器發(fā)送HTTP請(qǐng)求,而本身并不接收任何數(shù)據(jù) Inet1.Execute strURL, "GET" 為了檢索已達(dá)到數(shù)據(jù),我們需要使用GetChunk方法將緩沖區(qū)數(shù)據(jù)讀到VB變量中。 strBuffer = Inet1.GetChunk(512) strArrivedData = strArrivedData & strBuffer 可見,GetChnuk方法具有Size參數(shù),允許我們自定義從緩沖區(qū)內(nèi)讀出數(shù)據(jù)塊的大小。因此,我們找到了控制到達(dá)數(shù)據(jù)的方法,而且我們可以在下載過程中實(shí)現(xiàn)對(duì)已到達(dá)數(shù)據(jù)的控制。在StateChanged事件中加入如下代碼: Private Sub Inet1_StateChanged(ByVal State As Integer) Select Case State Case icResponseCompleted Do DoEvents strBuffer = Inet1.GetChunk(512) strArrivedData = strArrivedData & strBuffer lngArrivedDataSize = Len(strArrivedData) Loop Until Len(strBuffer) = 0 End Select End Sub OK!現(xiàn)在我們就能夠顯示已到達(dá)數(shù)據(jù)的大小了。但是如何獲得下載數(shù)量的百分比值,然后通過進(jìn)度條來顯示下載過程呢?首先,我們需要在任何數(shù)據(jù)到達(dá)之前知道頁面文件的大小。根據(jù)HTTP規(guī)范,Web服務(wù)器需要發(fā)送內(nèi)容長度報(bào)頭(Content-Length header field)作為HTTP請(qǐng)求的響應(yīng),通過這個(gè)值我們就可以知道頁面文件的大小。我們可以在StateChanged事件中調(diào)用ITC控件的GetHeader方法來獲取這個(gè)值,如下所示: 'This module level variable stores size of the file we are downloading from the web Private m_lngDocSize As Long Private Sub Inet1_StateChanged(ByVal State As Integer) Select Case State Case icResponseReceived If m_lDocSize = 0 Then If Len(Inet1.GetHeader("Content-Length")) > 0 Then m_lDocSize = CLng(Inet1.GetHeader("Content-Length")) End If End If End Select End Sub 然而,在某些情況下,Web服務(wù)器并不發(fā)送內(nèi)容長度報(bào)頭,我們也就不能知道頁面文件大小,也就不能顯示進(jìn)度信息了。 現(xiàn)在,我們來創(chuàng)建一個(gè)簡單的應(yīng)用程序來實(shí)現(xiàn)我們的目標(biāo)。 創(chuàng)建工程 啟動(dòng)VB集成開發(fā)環(huán)境,創(chuàng)建一個(gè)標(biāo)準(zhǔn)Windows應(yīng)用工程,將該工程命名為DownloadProgress,在Project菜單中打開Componets對(duì)話框(或按快捷鍵Ctrl+T激活),然后選中下列控件: • Microsoft Internet Transfer Control • Microsoft Rich Textbox Control • Microsoft Windows Common Controls 選擇保存目錄,然后保存該工程。 創(chuàng)建圖形用戶界面 在窗體上放置下列控件: • TextBox • CommandButton • 兩個(gè)Frame控件 • Label • ProgressBar • RichTextBox • Internet Transfer Control 如下圖所示,在窗體上對(duì)以上控件進(jìn)行布置。 編寫應(yīng)用程序代碼 打開窗體的代碼編輯器,在全局變量聲明部分(General-Declarations)部分進(jìn)行如下變量聲明。 Private m_lngDocSize As Long 這個(gè)變量將用來存儲(chǔ)我們將要下載的頁面大小。 下面,我們將對(duì)命令按鈕進(jìn)行編碼,在Command1_Click 事件中加入如下代碼: Private Sub Command1_Click() '文件大小值復(fù)位 m_lngDocSize = 0 '清空rtbDocument的文本 rtbDocument.Text = "" '復(fù)位進(jìn)度條控件 ProgressBar1.Value = 0.001 '顯示進(jìn)度的標(biāo)簽內(nèi)容設(shè)為空 lblProgressInfo.Caption = "" '定義ITC控件使用的協(xié)議為HTTP協(xié)議 Inet1.Protocol = icHTTP '調(diào)用Execute方法向Web服務(wù)器發(fā)送HTTP請(qǐng)求 If Len(txtURL.Text) > 0 Then Inet1.Execute Trim$(txtURL.Text), "GET" End If End Sub 在命令按鈕中,我們對(duì)各個(gè)控件的初值進(jìn)行了復(fù)位,并向Web服務(wù)器發(fā)送了HTTP請(qǐng)求,該URL地址由用戶鍵入到文本框中。在服務(wù)器開始響應(yīng)時(shí),我們需要處理ITC控件的StateChanged事件,從而獲得內(nèi)容長度報(bào)頭,并獲取隨后傳送過來的頁面過程信息。 Private Sub Inet1_StateChanged(ByVal State As Integer) Dim strText As String Dim strBuffer As String Dim sngProgerssValue As Single On Error Resume Next Select Case State Case icResponseCompleted Do '從緩沖區(qū)讀取數(shù)據(jù) DoEvents strBuffer = Inet1.GetChunk(512) strText = strText & strBuffer If m_lngDocSize > 0 Then If Len(strBuffer) > 0 Then '獲得進(jìn)度百分比值 sngProgerssValue = Int((Len(strText) / m_lngDocSize) * 100) End If '更新進(jìn)度標(biāo)簽顯示內(nèi)容 lblProgressInfo.Caption = "Downloaded " & CStr(Len(strText)) & _ " bytes (" & CStr(sngProgerssValue) & "%)" '用新值更新進(jìn)度條控件 ProgressBar1.Value = sngProgerssValue End If Loop Until Len(strBuffer) = 0 '將讀取的HTML頁面內(nèi)容置入RichTextBox控件 rtbDocument.Text = strText Case icResponseReceived If m_lngDocSize = 0 Then '讀取頁面文件大小 If Len(Inet1.GetHeader("Content-Length")) > 0 Then m_lngDocSize = CLng(Inet1.GetHeader("Content-Length")) End If End If End Select End Sub 一切OK!按F5測(cè)試這個(gè)新完成的應(yīng)用程序,在文本框內(nèi)鍵入任意存在的URL地址,然后點(diǎn)擊讀取按鈕,呵呵,成功了!(如果服務(wù)器發(fā)送了內(nèi)容長度報(bào)頭,我們就能看到結(jié)果,如果不發(fā)送,這個(gè)程序可就罷工了。) 下載源文件 http://www.ccw.com.cn/htm/app/down/020329.zip
|
溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!