You can actually download files in VB without extra dependancy to anything. You don't even need a single API call. The only requirement is a user control.
Below is a simple sample that has the ability to download multiple files at once, and your application remains responsive as well. It keeps track of the given keys (or "PropertyNames") so you won't run into an error condition if you try to download a file while it is already being downloaded. The control will cancel the existing download when that same file is being tried to download again.
Code:' Downloader.ctl Option Explicit Public Event Complete(ByRef URL As String, ByRef Data As String, ByRef Key As String) Public Event Progress(ByRef URL As String, ByRef Key As String, ByVal BytesDone As Long, ByVal BytesTotal As Long, ByVal Status As AsyncStatusCodeConstants) Public Enum DownloaderCache [Always download] = vbAsyncReadForceUpdate [Get cache copy only] = vbAsyncReadOfflineOperation [Update cached copy only] = vbAsyncReadResynchronize [Use cache if no connection] = vbAsyncReadGetFromCacheIfNetFail End Enum Private m_Keys As String Private Function Private_AddKey(ByRef Key As String) As Boolean ' see if we do not have the key Private_AddKey = InStr(m_Keys, vbNullChar & Key & vbNullChar) = 0 ' we can add it If Private_AddKey Then m_Keys = m_Keys & Key & vbNullChar End If End Function Private Sub Private_RemoveKey(ByRef Key As String) ' remove the key m_Keys = Replace(m_Keys, vbNullChar & Key & vbNullChar, vbNullChar) End Sub Public Sub Start(ByRef URL As String, Optional ByVal CacheMode As DownloaderCache = [Always download], Optional ByVal Key As String) ' use URL as key if no key is given If LenB(Key) = 0 Then Key = URL ' do we already have this key? If Not Private_AddKey(Key) Then ' cancel the old one CancelAsyncRead Key End If ' begin download process AsyncRead URL, vbAsyncTypeByteArray, Key, CacheMode End Sub Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty) Dim strData As String ' get Variant byte array to byte string (needs StrConv to Unicode for displaying in a textbox) If AsyncProp.BytesRead Then strData = AsyncProp.Value Else strData = vbNullString ' redirect information RaiseEvent Complete(AsyncProp.Target, strData, AsyncProp.PropertyName) ' remove the key Private_RemoveKey AsyncProp.PropertyName End Sub Private Sub UserControl_AsyncReadProgress(AsyncProp As AsyncProperty) With AsyncProp ' redirect event information If LenB(.PropertyName) Then RaiseEvent Progress(.Target, .PropertyName, .BytesRead, .BytesMax, .StatusCode) Else RaiseEvent Progress(.Target, vbNullString, .BytesRead, .BytesMax, .StatusCode) End If End With End Sub Private Sub UserControl_Initialize() m_Keys = vbNullChar End Sub
A sample application: you need two command buttons, one multiline textbox and a listbox. You need the user control as well.You can also download images directly as a Picture object. To see other possible values, open up Object Browser with F2 and type Async into the search field.Code:Option Explicit Private Sub Command1_Click() Downloader1.Start "http://merri.net/" End Sub Private Sub Command2_Click() Downloader1.Start "http://www.vbforums.com/" End Sub Private Sub Downloader1_Complete(URL As String, Data As String, Key As String) Me.Caption = URL Text1.Text = StrConv(Data, vbUnicode) End Sub Private Sub Downloader1_Progress(URL As String, Key As String, ByVal BytesDone As Long, ByVal BytesTotal As Long, ByVal Status As AsyncStatusCodeConstants) List1.AddItem URL & " @ " & (BytesDone \ 1024) & " kB, status code: " & Status, 0 End Sub
Possible issues
Showing a message box seems to entirely prevent events from triggering under the IDE. I haven't tested compiled, but I believe it works just fine there: timer events don't run in the IDE when a messagebox is shown, but compiled it works just fine.
Updates!
2008-09-14: changed Data to string from byte array and made a check for if any data was received to avoid an error.


Reply With Quote

