In letzter Zeit immer häufiger gefragt: "Wie kann ich eine Datei via HTTP, also anhand einer vorgegebenen URL-Adresse, aus dem Internet downloaden?" Hierzu gibt es mehrere Möglichkeiten. Wir zeigen Ihnen, wie sich ein Datei-Download unter Verwendung des Winsock-Controls realisieren lässt - und das ganze mit Klasse, als ActiveX-DLL eben. Nachfolgend zwei Möglichkeiten... Für den automatischen Datei-Download aus dem Internet aus Ihrer VB-Anwendung heraus, gibt es mehrere Möglichkeiten:
Variante 1: API - DoFileDownload Dies ist die wohl einfachste Lösung - hat aber einen für viele Programmierer unangenehmen Nebeneffekt: Der Download erfolgt über den Download-Dialog des Internet Explorers! Wer mit dieser Variante zufrieden ist, der braucht lediglich die nachfolgende API-Funktion in seine Anwendung zu übernehmen und mit den entsprechenden Parametern aufzurufen: Declare Function DoFileDownload Lib "shdocvw.dll" ( _ Byval lpszFile As String) As Long ' Download starten ' zunächst URL in Unicode konvertieren strURL = StrConv("http://MeineDomain.de/Download.exe", vbUnicode) DoFileDownload strURL Während des Download-Vorgangs erscheint natürlich ebenfalls der bekannte Fortschritts-Dialog des Microsoft Internet Explorers. Variante 2: Einsatz eines Winsock-Controls Die zweite Variante bedarf etwas mehr Programmierarbeit, welcher sich aber lohnen sollte. Unter Verwendung des Winsock-Controls kann der Datei-Download von der Anwendung gesteuert werden, d.h. der Download könnte z.B. völlig "unsichtbar" im Hintergrund erfolgen. Ebenso können Sie Ihren eigenen Download-Fortschrittsdialog einbinden. Und: Der Download selbst lässt sich natürlich auch programmgesteuert abbrechen! Nun könnte man das Ganze natürlich direkt in die jeweilige Anwendung einbauen - man könnte aber auch eine eigene Klasse erstellen - eine ActiveX-DLL. Diese DLL lässt sich dann per "Verweis" in allen Ihren Anwendungen einsetzen - ist also wesentlich flexibler. Datei-Download als ActiveX-DLL realisieren Starten Sie die Visual Basic Entwicklungsumgebung, wählen Sie "neues Projekt" und klicken im Auswahl-Dialog auf ActiveX-DLL. Öffnen Sie das Eigenschaftenfenster des Projekts und legen als Projektname classFileDownload fest. Dem Klassenmodul selbst geben Sie den Namen clsDownload und setzen die Eigenschaft Instancing = 5 - MultiUse. Wie bereits eingangs erwähnt benötigen wir das Winsock-Control. Fügen Sie dem Projekt also über Projekt - Komponenten das "Microsoft Winsock Control" hinzu. Um das Winsock-Control verwenden zu können, benötigen wir weiterhin eine Form. Also - neue Form hinzufügen und das Winsock-Control darauf plazieren. Die Form nennen wir frmWinsock. Eines gleich vorweg: Diese Form bleibt immer unsichtbar, denn wir brauchen ja nur die Eigenschaften, Methoden und Ereignisse des Winsock-Controls - die Form selbst nicht! Doppelklicken Sie im Projekt-Explorer nun auf das Klassenmodul clsDownload. Im Allgemein-Teil des Moduls fügen Sie nun alle benötigten Referenzen und Variablen ein: Option Explicit Private WithEvents mSockCtrl As MSWinsockLib.Winsock Private strRemoteHost As String Private strFilePath As String Private strLocalFilename As String Private bFinished As Boolean Private bHeaderSend As Boolean Private lngFileSize As Long ' Öffentliche Ereignisse Public Event Start() Public Event Progress(ByVal BytesLoaded As Long, _ ByVal FileSize As Long) Public Event Finished() Als erstes haben wir hier das Objekt mSockCtrl. Hierbei handelt es sich um ein Winsock-Objekt. Die Deklaration in Verbindung mit WithEvents ermöglicht es, dass wir innerhalb des Klassenmoduls alle Ereignisse des Winsock-Controls empfangen und dementsprechend reagieren können. Im unteren Teil der Deklarationen legen wir die öffentlichen Ereignis-Schnittstellen unserer ActiveX-DLL fest. Diese Ereignisse werden während des Download-Vorgangs gezielt ausgelöst, so dass die Hauptanwendung immer über den aktuellen Fortschritt informiert werden kann. ActiveX-DLL: DoDownload Die nachfolgende Prozedur DoDownload wird später innerhalb der Hauptanwendung aufgerufen, wenn eine Datei aus dem Internet geladen werden soll. Hierbei müssen als Parameter die Download-URL und der Dateiname, unter welchem die Datei lokal gespeichert werden soll, angegeben werden. ' Datei-Download Public Function DoDownload(ByVal strURL As String, _ ByVal strLocalFile As String) As Boolean ' Fehlerbehandlung aktivieren On Error GoTo Download_Error ' Ggf. http:// entfernen If LCase$(Left$(strURL, 7)) = "http://" Then strURL = Mid$(strURL, 8) End If ' RemoteHost strRemoteHost = Left$(strURL, InStr(1, strURL, "/") - 1) ' relativer Pfad strFilePath = Mid$(strURL, InStr(1, strURL, "/")) ' Lokaler Dateiname (ggf. löschen) strLocalFilename = strLocalFile If Dir$(strLocalFilename, vbNormal) <> "" Then Kill strLocalFilename End If ' Winsock-Control initialisiert ??? If mSockCtrl Is Nothing Then Dim frmTMP As New frmWinsock Set mSockCtrl = frmTMP.Winsock1 End If ' Variablen zurücksetzen bFinished = False bHeaderSend = False lngFileSize = 0 ' Verbindung herstellen With mSockCtrl .Close .LocalPort = 0 .Connect strRemoteHost, 80 End With On Error Resume Next Set frmTMP = Nothing Unload frmWinsock DoDownload = True Exit Function Download_Error: If Err.Number = 5 Then strURL = strURL & "/" Resume 0 Else MsgBox "Fehler!" & vbCrLf & "Error: " & Err.Number & _ vbCrLf & Err.Description, 16 End If DoDownload = False End Function Im Falle eines Fehlers gibt die Funktion den Wert False zurück. Sie sollten also in der Hauptanwendung den Rückgabewert des Funktionsaufruf unbedingt auswerten. Über die Methode .Connect strRemoteHost, 80 wird nun versucht eine Verbindung zum Webserver herzustellen - und zwar an Port 80, der üblicherweise bei HTTP-Anfragen verwendet wird. Sobald eine Verbindung zustande kommt, wird vom Winsock-Control das Ereignis Connect ausgelöst. Jetzt müssen wir dem Winsock-Control noch mitteilen, welche Aktion ausgeführt werden soll. Hierzu wird ein HTTP-Request (eine HTTP-Anfrage) an den Webserver geschickt - in unserem Fall also eine Download-Anfrage. ' Verbunden Private Sub mSockCtrl_Connect() Dim strHttpRequest As String ' HTTP-Request senden strHttpRequest = "GET " & strFilePath & " HTTP/1.1" & vbCrLf & _ "Host: " & strRemoteHost & vbCrLf & _ "Accept: */*" & vbCrLf & _ "Connection: close" & vbCrLf & vbCrLf mSockCtrl.SendData strHttpRequest ' Hauptanwendung mitteilen, dass der Datei-Download ' nun gestartet wird RaiseEvent Start End Sub Über RaiseEvent Start lösen wir jetzt das Ereignis Start aus, so dass die Hauptanwendung über den Start des Datei-Downloads informiert wird. Datenpakete empfangen und speichern Das Winsock-Control empfängt nun die Daten in einzelne Datenblöcke. Jedesmal wenn ein neuer Datenblock ankommt, wird das DataArrival-Ereignis ausgelöst. Wir brauchen jetzt also nur die empfangenen Daten lokal zu speichern. Das erste Datenpaket enthält i.a.R. noch zusätzliche Informationen über die Download-Datei selbst, wie Größe der Datei, letzte Änderung usw. Diese Informationen dürfen natürlich nicht in die lokale Datei gespeichert werden! Also müssen wir die Informationen vom eigentlichen Datenpaket trennen. Hierzu muss man wissen, dass die HTTP-Header Informationen immer mit einer Leerzeile enden. Alle Daten nach dieser Leerzeile gehören dann zur Datei. ' Daten werden empfangen Private Sub mSockCtrl_DataArrival(ByVal bytesTotal As Long) On Error Resume Next Static lngContentLength As Long Dim strData As String Dim strHttpHeader As String Dim F As Integer Dim lPos As Long ' Daten empfangen mSockCtrl.GetData strData ' Prüfen, ob HTTP-Header enthalten ' wenn ja: auswerten und entfernen If Not bHeaderSend And Left$(strData, 6) = "HTTP/1" Then strHttpHeader = Left$(strData, InStr(1, strData, _ vbCrLf & vbCrLf) + 3) ' Dateigröße ermitteln lPos = InStr(strHttpHeader, "Content-Length: ") If lPos > 0 Then lngContentLength = Val(Mid$(strHttpHeader, lPos + 15, _ InStr(Mid$(strHttpHeader, lPos), vbCrLf) - 1)) End If ' Header entfernen strData = Mid$(strData, Len(strHttpHeader) + 1) bHeaderSend = True End If If Not bHeaderSend Then lngContentLength = 0 ' Daten in Datei speichern F = FreeFile Open strLocalFilename For Append As #F Print #F, strData; Close #F ' Fortschritt lngFileSize = lngFileSize + Len(strData) RaiseEvent Progress(lngFileSize, lngContentLength) End Sub Jedesmal, wenn also ein Datenpaket empfangen wird, lösen wir das Ereignis Progress aus, so dass die Hauptanwendung über den aktuellen Download-Fortschritt informiert wird. Zusätzlich aktualisieren wir die Variablen lngFileSize (aktuell heruntergeladene Bytes) und lngContentLength (insgesamt herunterzuladende Bytes). Diese beiden Variablen stehen der Hauptanwendung im Ereignis Progress ebenfalls zur Verfügung (z.B. für eine Fortschrittsanzeige). Sobald die Datei vollständig heruntergeladen wurde, wird vom Winsock-Control das Ereignis Close ausgelöst. Über diesen Ereignis können wir also die Hauptanwendung ebenfalls über das Beenden des Download-Vorgangs informieren. ' Downlaod beendet Private Sub mSockCtrl_Close() If Not bFinished Then bFinished = True RaiseEvent Finished End If End Sub Das waren eigentlich schon alle notwendigen Schritte und Vorgänge für den Datei-Download. Um den Download-Vorgang auch aus der Hauptanwendung heraus programmgesteuert abbrechen zu können, fügen wir der Klasse noch eine öffentliche Prozedur AbortDownload hinzu. Wird diese Prozedur von der Hauptanwendung aufgerufen, wird die Verbindung zum Webserver getrennt und der Downlaod beendet. ' Download abbrechen Public Sub AbortDownload() On Local Error Resume Next mSockCtrl.Close Set mSockCtrl = Nothing End Sub Kompilieren als ActiveX-DLL und anwenden! Unsere ActiveX-DLL ist hiermit vollständig. Das Projekt kann nun kompiliert werden. Wählen Sie hierzu den Befehl "classFileDownload.dll erstellen" im Menü "Datei". Aktivieren Sie gleich danach den Eigenschaften-Dialog des Projekts (Menü Projekt - Eigenschaften), wechseln in die Registerkarte Komponente und aktivieren die Option Binär-Kompatibilität. Klicken Sie auf "OK" und kompilieren Sie das Projekt erneut. Um die neu erstelte ActiveX-DLL in der eigenen Anwendung nutzen zu können, müssen Sie einen Verweis zur DLL einfügen. Dies erfolgt über das Menü "Projekt - Verweise". In der Form, in der Sie einen Datei-Download ausführen möchten, fügen Sie folgenden Code ein: ' Allgemein-Teil der Form Dim WithEvents FileDownload As clsDownload ' Datei downloaden Private Sub cmdDownload_Click() Set FileDownload = New clsDownload FileDownload.DoDownload "URL", "Dateiname" End Sub ' Download beendet Private Sub FileDownload_Finished() Set FileDownload = Nothing End Sub Ein Beispiels-Projekt Starten Sie die Visual Basic Entwicklungsumgebung und erstellen ein neues Projekt. Setzen Sie anschliessend einen Verweis auf die "classFileDownload.dll" (Menü Projekt - Verweise). Plazieren Sie auf die Form1 zwei Textfelder - txtURL und txtLocal, zwei CommandButtons - cmdStart und cmdAbort, sowie eine PictureBox picProgress und darunter ein Label lblStatus. Fügen Sie in den Codeteil der Form nachfolgenden VB-Code: Option Explicit Dim WithEvents FileDownload As clsDownload Private Sub Form_Load() cmdStart.Enabled = True cmdAbort.Enabled = False lblStatus.Visible = False End Sub ' Download starten Private Sub cmdStart_Click() Dim strURL As String ' Prüfen, ob überhaupt irgendeine URL eingegeben wurde If Len(txtURL.Text) = 0 Then MsgBox "Bitte zunächst eine gültige URL eingeben", 64 Exit Sub End If ' Prüfen, ob ein lokaler Dateiname eingegeben wurde If Len(txtLocal.Text) = 0 Then MsgBox "Bitte zunächst einen lokalen Dateinamen eingeben", 64 Exit Sub End If ' Download beginnen Set FileDownload = New clsDownload If FileDownload.DoDownload(txtURL.Text, txtLocal.Text) Then cmdStart.Enabled = False cmdAbort.Enabled = True Else Set FileDownload = Nothing End If End Sub ' Download abbrechen Private Sub cmdAbort_Click() If MsgBox("Download wirklich abbrechen?", 292, _ "Download") = vbYes Then FileDownload.AbortDownload lblStatus.Caption = "Download abgebrochen." cmdStart.Enabled = True cmdAbort.Enabled = False End If End Sub ' Download beendet Private Sub FileDownload_Finished() lblStatus.Caption = "Download beendet." Set FileDownload = Nothing cmdStart.Enabled = True cmdAbort.Enabled = False End Sub ' Download-Fortschritt Private Sub FileDownload_Progress(ByVal BytesLoaded As Long, ByVal FileSize As Long) lblStatus.Caption = CStr(BytesLoaded) & " von " & _ CStr(FileSize) & " Bytes" ShowProgress picProgress, BytesLoaded, 0, FileSize End Sub ' Download wurde gestartet Private Sub FileDownload_Start() lblStatus.Visible = True End Sub ' Fortschritsanzeige Private Sub ShowProgress(picProgress As PictureBox, _ ByVal Value As Long, _ ByVal Min As Long, _ ByVal Max As Long, _ Optional ByVal bShowProzent As Boolean = True) Dim pWidth As Long Dim intProz As Integer Dim strProz As String ' Farben Const progBackColor = &HC00000 Const progForeColor = vbBlack Const progForeColorHighlight = vbWhite ' Plausibilitätsprüfungen If Value < Min Then Value = Min If Value > Max Then Value = Max ' Prozentwert ausrechnen If Max > 0 Then intProz = Int(Value / Max * 100 + 0.5) Else intProz = 100 End If With picProgress ' Prüfen, ob AutoReadraw=True If .AutoRedraw = False Then .AutoRedraw = True ' Inhalt löschen picProgress.Cls If Value > 0 Then ' Balkenbreite pWidth = .ScaleWidth / 100 * intProz ' Balken anzeigen picProgress.Line (0, 0)-(pWidth, .ScaleHeight), _ progBackColor, BF ' Prozentanzeige If bShowProzent Then strProz = CStr(intProz) & " %" .CurrentX = (.ScaleWidth - .TextWidth(strProz)) / 2 .CurrentY = (.ScaleHeight - .TextHeight(strProz)) / 2 ' Vordergrundfarbe If pWidth >= .CurrentX Then .ForeColor = progForeColorHighlight Else .ForeColor = progForeColor End If picProgress.Print strProz End If End If End With End Sub Viel Spass mit der neuen FileDownlaod - ActiveX-DLL! Dieter Dieser Workshop wurde bereits 42.790 mal aufgerufen.
Anzeige
Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
vb@rchiv CD Vol.6 Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! Online-Update-Funktion Entwickler-Vollversionen u.v.m. Tipp des Monats Oktober 2024 Heinz Prelle Firewall-Status unter WinXP/Vista prüfen Das Beispiel prüft, ob die Firewall unter Windows XP/Vista eingeschaltet ist oder nicht. Zudem wird eine Abfrage durchgeführt ob es sich bei dem zugrundeliegenden Betriebssystem um Windows XP/Vista handelt oder nicht. sevGraph (VB/VBA) Grafische Auswertungen Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! |
|||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |