程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB綜合教程 >> 用VB編寫異步多線程下載程序

用VB編寫異步多線程下載程序

編輯:VB綜合教程
為了高效率地下載某站點的網頁,我們可利用VB的InternetTransfer控件編寫自己的下載程序,InternetTransfer控件支持超文本傳輸協議(HTTP)和文件傳輸協議(FTP),使用InternetTransfer控件可以通過OpenURL或Execute方法連接到任何使用這兩個協議的站點並檢索文件。本程序使用多個InternetTransfer控件,使其同時下載某站點。並可判斷文件是否已下載過或下載過的文件是否比服務器上當前的文件陳舊,以決定是否重新下載。所有下載的文件中的鏈接都做了調整,以便於本地查閱。
  OpenURL方法以同步方式傳輸數據。同步指的是傳輸操作未完成之前,不能執行其它過程。這樣數據傳輸就必須在執行其它代碼之前完成。
  而Execute方法以異步方式傳輸數據。在調用Execute方法時,傳輸操作與其它過程無關。這樣,在調用Execute方法後,在後台接收數據的同時可執行其它代碼。
  用OpenURL方法能夠直接得到可保存到磁盤的數據流,或者直接在TextBox控件中閱覽(如果數據是文本格式的)。而用Execute方法獲取數據,則必須用StateChanged事件監視該控件的連接狀態。當達到適當的狀態時,調用GetChunk方法從控件的緩沖區獲取數據。
  
  首先,建立啟始的http檢索連接,
  PublicgAsVariant
  PublickAsVariant
  PublicspathAsString
  Dimlinks()AsString
  g=0
  spath=本地保存下載文件的路徑
  links(0)=啟始URL
  inet1.executelinks(0),"GET"'使用GET方法。
  
  事件監控子程序(每個InternetTransfer控件設置相對應的事件監控子程序):
  用StateChanged事件監視該控件的連接狀態,當該請求已經完成,並且所有數據均已接收到時,調用GetChunk方法從控件的緩沖區獲取數據。
  PrivateSubInet1_StateChanged(ByValStateAsInteger)
  'State=12時,使用GetChunk方法檢索服務器的響應。
  SelectCaseState
  '...沒有列舉其它情況。
  
  CaseicResponseCompleted'12
  '獲取links(g)中的協議、主機和路徑名。
  addsuf=Left(links(g),InStrRev(links(g),"/"))
  '獲取links(g)中的文件名。
  fname=Right(links(g),Len(links(g))-InStrRev(links(g),"/"))
  '判斷是否是超文本文件,是超文本文件則分析其中的鏈接,若不是則存為二進制文件。
  IfInStr(1,fname,"htm",vbTextCompare)=TrueThen
  '初始化用於保存文件的FileSystemObject對象。
  Setfs=CreateObject("Scripting.FileSystemObject")
  DimvtDataAsVariant'數據變量。
  DimstrDataAsString:strData=""
  DimbDoneAsBoolean:bDone=False
  
  '取得第一塊。
  vtData=inet1.GetChunk(1024,icString)
  DoEvents
  DoWhileNotbDone
  strData=strData&vtData
  DoEvents
  '取得下一塊。
  vtData=inet1.GetChunk(1024,icString)
  IfLen(vtData)=0Then
  bDone=True
  EndIf
  Loop
  
  '獲取文檔中的鏈接並置於數組中。
  DimiAsVariant
  Dimpo1AsVariant
  Dimpo2AsVariant
  DimorilAsString
  DimnewlAsString
  Dimlmtime,ctime
  po1=InStr(1,strData,"href=",vbTextCompare) 5
  po2=1
  DimnewstrAsString:newstr=""
  DimwhostrAsString:whostr=""
  i=0
  DoWhilepo1>0
  newstr=Mid(strData,po2,po1)
  whostr=whostr newstr
  po2=InStr(po1,strData,">",vbTextCompare)
  '將原鏈接改為新鏈接
  oril=Mid(strData,po1 1,po2-po1-1)
  '如果有引號,去掉引號
  ln=Replace(oril,"""","",vbTextCompare)
  newl=Right(ln,Len(ln)-InStrRev(ln,"/"))
  whostr=whostr&newl
  Ifln<>""Then
  '判定文件是否下載過。
  Iffileexists(spath&newl)=FalseThen
  links(i)=addsuf&ln
  i=i 1
  Else
  lmtime=inet1.getheader("Last-modified")
  Setf=fs.getfile(spath&newl)
  ctime=f.datecreated
  '判斷文件是否更新
  IfDateDiff("s",lmtime,ctime)<0Then
  i=i 1
  EndIf
  EndIf
  EndIf
  po1=InStr(po2 1,strData,"href=",vbTextCompare) 5
  Loop
  newstr=Mid(strData,po2)
  whostr=whostr newstr
  
  Seta=fs.createtextfile(spath&fname,True)
  a.Writewhostr
  a.Close
  k=i
  Else
  DimvtDataAsVariant
  Dimb()AsByte
  DimbDoneAsBoolean:bDone=False
  vtData=Inet2.GetChunk(1024,icByteArray)
  DoWhileNotbDone
  b()=b()&vtData
  vtData=Inet2.GetChunk(1024,icByteArray)
  IfLen(vtData)=0Then
  bDone=True
  EndIf
  Loop
  Openspath&fnameForBinaryAccessWriteAs#1
  Put#1,,b()
  Close#1
  EndIf
  Calldevjob'調用線程調度子程序
  EndSelect
  
  EndSub
  
  PrivateSubInet2_StateChanged(ByValStateAsInteger)
  ...
  endsub
  
  ...
  
  線程調度子程序,g和是k公用變量,k為最後一個鏈接的數組索引加一,g初值為零,每次加一,直到處理完最後一個鏈接。
  PrivateSubdevjob()
  
  IfNotg 1<kThenGoToreportline
  IfInet1.StillExecuting=FalseThen
  g=g 1
  Inet1.Executelinks(g),"GET"
  EndIf
  IfNotg 1<kThenGoToreportline
  IfInet2.StillExecuting=FalseThen
  g=g 1
  Inet2.Executelinks(g),"GET"
  EndIf
  
  ...
  
  reportline:
  IfInet1.StillExecuting=FalseAndInet2.StillExecuting=FalseAnd...Then
  MsgBox("下載結束。")
  EndIf
  EndSub->

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved