vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Mails senden, abrufen und decodieren - ganz easy ;-)  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2017
 
zurück
Rubrik: Internet/Netzwerk   |   VB-Versionen: VB5, VB615.11.01
Datei-Download via HTTP-Protokoll

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.

Autor:  Dieter OtterBewertung:     [ Jetzt bewerten ]Views:  35.267 

Neue Version! sevEingabe 3.0 (für VB6 und VBA)
Das Eingabe-Control der Superlative! Noch besser und noch leistungsfähiger!
Jetzt zum Einführungspreis       - Aktionspreis nur für kurze Zeit gültig -

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:

  1. Aufruf der API-Funktion "DoFileDownload"
  2. Verwendung des Winsock-Controls

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!

Starten des Downloads - Der bekannte Download-Dialog erscheint

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

Ebenfalls die bekannte Fortschrittsanzeige während des Download-Vorgangs

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!

Dateidownload mit eigenem Fortschrittsdialog

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

Dateidownload mit eigenem Fortschrittsdialog

Viel Spass mit der neuen FileDownlaod - ActiveX-DLL!

Dieter

Dieser Workshop wurde bereits 35.267 mal aufgerufen.

Über diesen Workshop im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Aktuelle Diskussion anzeigen (36 Beiträge)

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!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.
 
   

Druckansicht Druckansicht Copyright ©2000-2017 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
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.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel