ในบทความนี้เราจะใช้ คอมโพแนนต์
ที่ชื่อว่า Internet Transfer Control (ITC) ซึ่งเป็น คอนโทรล
ที่ง่ายใช้ในการเขียนโปรแกรม รับส่งข้อมูลทางอินเทอร์เน็ต แต่เสียอยู่ที่ว่า
ไม่มีส่วนของ การแสดงสถานะการดาวน์โหลดที่กำลังส่งผ่านอยู่ในขณะนั้น
มันคงจะดี ถ้าคอนโทรลนี้มี พรอพเพอร์ตี้ DownloadProgress หรือว่า
อีเวนต์ DataArrival ที่มี parameter ที่สามารถนำมาใช้ได้เลย.
เราจะใช้ 2 เมธอดของ ITC
ในการดาวน์โหลดเว็บเพจ คือ OpenURL กับ Execute. เมธอด OpenURL
จะเป็นเมธอดที่ใช้งานง่ายเมธอดนึง แต่มันจะมีข้อจำกัด และเราไม่สามารถจะรับข้อมูลที่เกี่ยวกับสถานะการดาวน์โหลด
โดยใช้เมธอดนี้ได้เลย ในการรับข้อมูลจากเว็บเพจโดยใช้เมธอด OpenURL
เราจะมีรูปแบบของโค้ดดังนี้:
strPageContent
= Inet1.OpenURL(strURL, icString)
คุณจะเห็นว่ามันง่ายที่จะรับข้อมูลเว็บเพจมา
ด้วยการใช้เมธอด OpenURL แต่ ITC ก็ไม่ได้ส่งข้อมูลอะไรที่เกี่ยวกับจำนวนของข้อมูลที่ส่งมา
และเราก็ไม่สามารถที่จะควบคุมข้อมูลที่เข้ามาได้ ถ้าเป็นอย่างนั้น
เราคงจำเป็นที่จะต้องเข้าถึงข้อมูลที่อยู่ใน Winsock buffer
ซึ่งเป็นส่วนที่เก็บข้อมูลที่ถูกส่งมา ถ้าเราเข้าถึงข้อมูลนั้นได้
เราก็สามารถที่จะคำนวณขนาดของข้อมูลที่กำลังส่งมาได้
'เมธอด
Execute จะส่งการร้องขอ HTTP ไปยังเว็บเซิร์ฟเวอร์
Inet1.Execute strURL,
"GET"
ในการรับข้อมูลที่จะเข้ามาเราจำเป็นที่จะใช้เมธอด
GetChunk ในการรับข้อมูลจากบัฟเฟอร์เข้าไปยังตัวแปร
strBuffer
= Inet1.GetChunk(512)
strArrivedData = strArrivedData & strBuffer
ประเด็นตอนนี้อยู่ที่ว่าเมธอด
GetChunk จะรับอาร์กิวเมนต์ที่เป็นตัวกำหนดขนาดของข้อมูลซึ่งจะได้จากบัฟเฟอร์
ซึ่งทำให้เราสามารถกำหนดขนาดของข้อมูลได้ ดังนั้นเราจึงสามารถควบคุมปริมาณข้อมูลที่เข้ามาได้
ยิ่งไปกว่านั้น เราสามารถที่จะทำได้ในระหว่างที่ทำการดาว์นโหลด
โดยคัดลอกโค้ดต่อไปนี้ เอาไปใส่ใน ส่วนของอีเวนต์ 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
เอาละครับ , ตอนนี้เราสามารถที่จะแสดงจำนวนของข้อมูลที่เข้ามา
แต่จะทำยังไงที่จะคิดให้ออกมาเป็นเปอร์เซ็นต์ เพื่อที่จะใช้กับคอนโทรลที่ชื่อ
ProgressBar เราจำเป็นที่จะต้องรู้ขนาดของไฟล์ที่เราจะรับก่อนที่ข้อมูลจะเข้ามา
ความจริงแล้วจากข้อกำหนดของ HTTP ที่กำหนดให้เว็บเซิร์ฟเวอร์ส่ง
Content-Length header ไปพร้อมกับ HTTP response โดยฟิลด์ดังกล่าวจะบ่งบอกถึงขนาด
ในการที่เราจะรับฟิลด์ดังกล่าวด้วย ITC เราจะต้องเรียกใช้เมธอด
GetHeader ภายในโพรซีเจอร์ StateChanged
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
โชคร้าย ที่มีบางลักษณะที่
เว็บเซิร์ฟเวอร์จะไม่ส่งฟิลด์ Content-Length header ,และเราจะไม่สามารถหาขนาดและแสดงสถานะการทำงานได้
เอาละครับ ต่อไปเราจะมาสร้างโปรแกรมตัวอย่างที่แสดงการทำงานให้เห็นกันเลยนะครับ
สร้างโปรเจ็กต์
เริ่มต้นจากการเปิดโปรแกรม
Visual Basic แล้วสร้างโปรเจ็กต์ Standard EXE กำหนดชื่อโปรเจ็กต์เป็น
DownloadProgress กดปุ่ม Ctrl+T เพื่อเรียกไดอะล็อกComponents
แล้วทำการเลือกเช็กบอกซ์ต่อไปนี้:
- Microsoft Internet
Transfer Control
- Microsoft Rich Textbox
Control
- Microsoft Windows
Common Controls
ทำการบันทึกโปรเจ็กต์
การสร้าง
GUI
วางคอนโทรลต่อไปนี้ลงบนฟอร์มของโปรเจ็กต์:
- TextBox
- CommandButton
- Two Frame controls
- Label
- ProgressBar
- RichTextBox
- Internet Transfer
Control
จัดตำแหน่งของคอนโทรล
ตามรูปด้านล่างนี้:
โค้ดของโปรแกรม
เปิดหน้าต่างเพื่อแก้ไขโค้ด
แล้วทำการประกาศตัวแปรลงในส่วนของGeneral-Declarations
:
Private
m_lngDocSize As Long
|
ตัวแปรนี้จะใช้ในการเก็บขนาดของข้อมูลที่เราจะดาว์นโหลด
ขั้นตอนต่อไปคือ การใส่โค้ดที่จะทำงานเมื่อมีการคลิกปุ่ม
โดยจะใส่โค้ดนี้ลงในส่วนของโพซีเจอร์ Command1_Click:
Private Sub Command1_Click()
'
'reset file size value
m_lngDocSize = 0
'clear rtbDocument
rtbDocument.Text = ""
'
'reset the ProgressBar control
ProgressBar1.Value = 0.001
'
'clear the label control
lblProgressInfo.Caption = ""
'
'define protocol for the ITC
Inet1.Protocol = icHTTP
'
'call the Execute method to send
'HTTP request to the webserver
If Len(txtURL.Text) > 0 Then
Inet1.Execute Trim$(txtURL.Text), "GET"
End If
'
End Sub
|
โค้ดข้างต้น จะเป็นในส่วนของการกำหนดค่าเริ่มต้นสำหรับคอนโทรล
และส่งคำร้องขอ (request) ไปยังเว็บเซิร์ฟเวอร์ ที่ผู้ใช้โปรแกรมต้องการ
เมื่อเซิร์ฟเวอร์ตอบสนอง (respond) เราก็จะเขียนโค้ดลงในส่วนของอีเวนต์
StateChanged ของ Internet Transfer Control เพื่อที่จะรับค่าข้อมูล
Content-Length header และข้อมูลที่จะเข้ามา
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
'retrieve data from the buffer
Do
DoEvents
'
strBuffer = Inet1.GetChunk(512)
strText = strText & strBuffer
'
If m_lngDocSize > 0 Then
If Len(strBuffer) > 0 Then
'get percent value
sngProgerssValue = Int((Len(strText) / m_lngDocSize) * 100)
End If
'update the label control with new caption
lblProgressInfo.Caption = "Downloaded " & CStr(Len(strText)) & _
" bytes (" & CStr(sngProgerssValue) & "%)"
'update the PregressBar control with new value
ProgressBar1.Value = sngProgerssValue
End If
'
Loop Until Len(strBuffer) = 0
'
'put retrieved HTML source into the RichTextBox control
rtbDocument.Text = strText
'
Case icResponseReceived
'
If m_lngDocSize = 0 Then
'
'retrieve size of the document
If Len(Inet1.GetHeader("Content-Length")) > 0 Then
m_lngDocSize = CLng(Inet1.GetHeader("Content-Length"))
End If
'
End If
'
End Select
'
End Sub
|
กดปุ่ม F5 เพื่อทดสอบโปรแกรม ป้อน
URL ที่ต้องการลงใน textbox แล้วทำการคลิกปุ่ม แล้วดูความเปลี่ยนแปลงที่เกิดขึ้น
ถ้าเซิร์ฟเวอร์มีการส่งฟิลด์ Content-Length header เราก็จะเห็นสถานะการดาวน์โหลดเว็บเพจ
แต่ถ้าไม่มีฟิลด์นี้ ก็จะไม่สามารถแสดงสถานะได้.
|