Im ersten Teil unseres "FTP"-Workshops haben wir Ihnen die grundlegende Vorgehensweise für das Herstellen einer Verbindung zu einem externen FTP-Server, sowie alle hierfür notwendigen Befehle und Funktionen vorgestellt. Der zweite Teil widmet sich nun dem Up- und Download von Dateien. Auch möchten wir Ihnen zeigen, wie sich ein abgebrochener Up- oder Download-Vorgang zu einem späteren Zeitpunkt wieder fortsetzen lässt. Somit sollten Sie am Ende dieses Workshops über alle Informationen verfügen, um Ihren eigenen FTP-Clienten zu programmieren. Kurzer Rückblick Mit den aus Teil 1 vorgestellten Befehlen und Funktionen konnte bisher folgendes durchgeführt werden:
Was jetzt noch fehlt, sind die entsprechenden Befehle, um eine auf der Festplatte lokal gespeicherte Datei in ein Verzeichnis des FTP-Servers hochzuladen (Upload), sowie umgekehrt eine auf dem FTP-Server vorhandene Datei lokal auf die Festplatte zu speichern (Download). Download einer Datei Beginnen wir mit dem Download-Vorgang. Für den Download von Dateien benötigen wir ein drittes Winsock-Steuerelement. Wir nennen es DownSock. Voraussetzung für einen erfolgreichen Download ist, dass zunächst eine Verbindung zum FTP-Server hergestellt wurde. Nachdem wir uns also am FTP-Server angemeldet haben und die Verbindung zustande gekommen ist, müssen wir zunächst wieder einen eindeutigen Port für das Empfangen der Daten öffnen. Ach so, ja - zuvor setzen wir den Übertragungsmode noch auf Binary. ' Datei downloaden Friend Function DownloadFile(ByVal LocalFile As String, _ ByVal ServerFile As String, _ ByVal ServerFileSize As Long, _ Optional ByVal StartDownloadAt As Long = 0) Dim TmpPort As Long Dim TmpPortStr As String ' Servermodus auf Binär stellen If SendCommand(OvermitBinary, CommandOk, CommandOk, _ CommandFail) = False Then Exit Function NewUniquePort: ' Port öffnen (für das Empfangen von Daten) TmpPort = 0 ' Neuen Port ermitteln Call GetNewPort(TmpPort, TmpPortStr) ' Neuen Port öffnen With Downsock .Close .LocalPort = TmpPort .Listen End With ' neu geöffneten Port dem Server mitteilen If SendCommand(SetPort & TmpPortStr, CommandOk, _ CommandOk, CommandFail, 0&, "Neuer Port geöffnet") = False Then Exit Function End If ' Download-Startposition setzen If SendCommand(ResumeTransfere & StartDownloadAt, _ ResumingSupportet, CommandOk, _ CommandNotImplemented) = False Then Exit Function ' Progressbar einstellen ' siehe Workshop-Projekt ' lokale Datei öffnen/erstellen FFile = FreeFile Open LocalFile For Binary As FFile Seek #FFile, StartDownloadAt + 1 ' Download-Anfrage an Server senden TAbort = False TotalBytes = ServerFileSize OvermittedBytes = StartDownloadAt SendCommand Download & ServerFile, TransferComplete, _ TransferComplete, DataConnectionClosed, TransferStart ' Warten bis das letzte Datenpäckchen übermittelt ' wurde Do DoEvents Loop Until Downsock.State <> sckConnected ' Socket schließen Downsock.Close ' Neue Datei schließen If FFile <> -1 Then Close FFile FFile = -1 End If ' Falls abgebrochen wurde If TAbort = True Then ... End If ' Falls die Verbindung zur Datenleitung nicht ' aufgebaut werden konnte nochmals versuchen If LastServerCmd = DataConnectionError Then GoTo NewUniquePort End Function Wie Sie bereits an der Parameter-Deklaration der Prozedur DownloadFile erkennen können, lässt sich hier optional angeben, ob der Datei-Download ab einer bestimmten Datei-Position fortgesetzt werden soll (für den Fall, dass ein voriger Download abgebrochen wurde). Hierzu muss die entsprechende Position im Parameter StartDownloadAt angegeben werden. Nach dem Senden der Download-Anfrage muss zunächst auf die Server-Antwort gewartet werden: ' Server-Verbindungsaufbau "genehmigen" Private Sub DownSock_ConnectionRequest(ByVal requestID As Long) With Downsock If .State = sckListening Then .Close Do DoEvents Loop Until .State = sckClosed .Accept requestID End If End With End Sub Immer wenn der Server uns Daten schickt, wird das DataArrival-Ereignis ausgelöst. Hier müssen wir nun die empfangenen Daten speichern (an die lokal geöffnete Datei "anhängen"). Desweiteren bietet sich hier auch bestens die Gelegenheit, eine evtl. vorhandene Statusanzeige zu aktualisieren: ' Server Daten erreichen uns Private Sub DownSock_DataArrival(ByVal bytestotal As Long) Dim TmpData As String ' Falls keine Bytes oder lokale Datei nicht ' geöffnet, Prozedur verlassen If bytestotal = 0 Or FFile = -1 Then Exit Sub ' Bisher empfangene Bytes aufaddieren OvermittedBytes = OvermittedBytes + bytestotal ' Daten an die lokal geöffnete Datei "anhängen" Downsock.GetData TmpData Put #FFile, , TmpData ' Download-Fortschritt aktualisieren ShowProgress picProgress, OvermittedBytes, 0, TotalBytes End Sub Abbrechen eines Up-/Downloads Natürlich sollten wir auch eine Möglichkeit vorsehen, dass man einen Up- oder Download jederzeit manuell (per Knopdruck) abbrechen kann. Hierzu speichern wir uns den Abbruch in der Variablen TAbort. Während des Up- bzw. Downloads wird diese Variable ständig abgefragt, so dass die Schleife für das Uploaden bzw. Downloaden der Datenpakete beendet werden kann. ' Dateiübertragung abbrechen Friend Function TransfereAbort() ' Abbruch-Kommando an den Server schicken SendCommand AbortTransfere, TransferComplete, _ TransferComplete, -1& ' Abbruch-Variable auf True setzen TAbort = True End Function Upload einer Datei Für den Upload-Vorgang verwenden wir ebenfalls das "neue" Downsock-Control. Der Upload selbst erfolgt immer in kleinen Datenpaketen, welche nach und nach an den FTP-Server geschickt werden. Jedesmal, wenn wir ein Datenpaket verschickt haben, müssen wir warten, bis der Server die Daten erhalten und bestätigt hat. Dann folgt das nächste - eben solange, bis die gesamte Datei auf den Server "hochgeladen" wurde. Sind alle Daten übertragen, wird die Datenverbindung wieder geschlossen. Natürlich möchten wir auch hier wieder während des Upload-Vorgangs den Fortschritt in Form einer Balkengrafik anzeigen. Ebenso soll es auch möglich sein, den Vorgang jederzeit abbrechen zu können. ' Datei "uploaden" Friend Function UploadFile(ByVal LocalFile As String, _ ByVal ServerFile As String, _ Optional ByVal StartUploadAt As Long = 0) Dim TmpPort As Long Dim TmpPortStr As String Dim SendBuff As String ' Servermodus auf Binär stellen If SendCommand(OvermitBinary, CommandOk, CommandOk, _ CommandFail) = False Then Exit Function NewUniquePort: ' Port öffnen (für das Senden der Daten) TmpPort = 0 ' Neuen Port ermitteln Call GetNewPort(TmpPort, TmpPortStr) ' Neuen Port öffnen With Downsock .Close .LocalPort = TmpPort .Listen End With ' neu geöffneten Port dem Server mitteilen If SendCommand(SetPort & TmpPortStr, CommandOk, CommandOk, _ CommandFail, 0&, "Neuer Port geöffnet") = False Then Exit Function End If ' Upload-Startposition setzen SendCommand ResumeTransfere & StartUploadAt, _ ResumingSupportet, CommandOk, CommandNotImplemented ' Progressbar einstellen ' siehe Workshop-Projekt ' lokale Datei öffnen FFile = FreeFile Open LocalFile For Binary As FFile Seek #FFile, StartUploadAt + 1 ' Anfrage an Server senden TAbort = False TotalBytes = LOF(FFile) OvermittedBytes = StartUploadAt If SendCommand(Upload & ServerFile, TransferStart, _ TransferStart, PermissionDenied) = False Then ' Zugriff verweigert (auf der Server-Seite) ... Exit Function End If ' Warten bis die Datenleitung verbunden ist Dim TimeOut As Long TimeOut = GetTickCount + 1000 * ConnectTimeOut Do DoEvents Loop Until Downsock.State = sckConnected Or _ TimeOut < GetTickCount / 1000 ' TimeOut überschritten! If Downsock.State <> sckConnected Then Exit Function ' Alle Daten senden und warten bis die Daten den ' Server erreichen PacketSend = True Do DoEvents ' Wenn vorheriges Päckchen beim Server ist, ' neues Daten-Päckchen senden If PacketSend = True And _ OvermittedBytes <> TotalBytes Then ' Puffergröße festlegen If TotalBytes - OvermittedBytes < SendBufferLenght Then SendBuff = Space(TotalBytes - OvermittedBytes) Else SendBuff = Space(SendBufferLenght) End If ' Übertragene Bytes aufaddieren OvermittedBytes = OvermittedBytes + Len(SendBuff) ' Progressbar aktualisieren ShowProgress picProgress, OvermittedBytes, 0, TotalBytes ' Daten aus der Datei lesen Get #FFile, , SendBuff ' Daten an den Server schicken If TAbort = True Then Exit Do PacketSend = False Downsock.SendData SendBuff End If Loop Until TotalBytes = OvermittedBytes And PacketSend = True ' Socket schließen Downsock.Close SendCommand "", TransferComplete, TransferComplete, -1& ' Für den nächsten Down-/Upload zurücksetzen OvermittedBytes = 0 TotalBytes = 0 ' Datei schließen If FFile <> -1 Then Close FFile FFile = -1 End If ' Falls abgebrochen wurde If TAbort = True Then ... End If ' Falls die Verbindung zur Datenleitung nicht ' aufgebaut werden konnte, nochmals versuchen If LastServerCmd = DataConnectionError Then GoTo NewUniquePort End Function Wie bereits schon bei der Download-Prozedur lässt sich auch bei ein abgebrochener Upload-Vorgang ab einer bestimmten Dateiposition fortsetzen. Hierzu muss einfach dem Parameter StartUploadAt die entsprechende Bytes-Position innerhalb der Datei mitgeteilt werden. Immer wenn wir (besser gesagt das Winsock-Control - in unserem Fall das Downsock-Control) ein Datenpaket verschickt haben, wird das Ereignis SendComplete ausgelöst. Dies ist dann auch die "richtige Stelle", an der wir die Variable PaketSend auf True setzen, so dass sich im Anschluss daran, das nächste Datenpaket auf den Weg machen kann ' Wenn beim Upload die Daten gesendet sind, ' Variable auf True stellen Private Sub DownSock_SendComplete() PacketSend = True End Sub Alle wichtigen Kommandos an den Server Ein richtiger FTP-Client kann natürlich noch mehr, als nur Verzeichnisse anzeigen und Dateien up- und downzuloaden. Standard-Befehle, wie Dateien und Verzeichnisse löschen oder Dateien und Verzeichnisse umbenennen sollte demnach zur "Grundausstattung" gehören. Alle diese Befehle sind FTP-Kommandos, welche an den Server geschickt werden. Hierbei handelt es sich um Strings (z.B. STOR - um Dateien zu senden), welche immer mit einem vbCrLf-Zeichen beendet werden müssen. Erwartet ein Kommando einen Parameter, wie z.B. den Verzeichnisnamen beim Wechseln des Verzeichnisses, so wird dieser Paramater getrennt durch ein Leerzeichen direkt hinter dem Kommando angegeben. Nachfolgend eine Liste mit den wichtigsten FTP-Kommandos:
Alle wichtigen Server-Rückmeldungen Nach dem Senden eines Kommandos an den Server (siehe Tabelle FTP-Kommandos) muss immer auf die Server-Anwort gewartet werden. Hierbei handelt es sich um eine dreistellige Zahl, die einen Status oder eine erwartete Aktion beschreibt. Serverkommandos sind nur abgeschlossen, wenn der Zahl ein Leerzeichen folgt. Abgeschlossen sind die Kommandos wieder durch ein vbCrLf-Zeichen. Enthält die Server-Rückmeldung zusätzlicher Parameter, so sind diese durch ein Leerzeichen getrennt direkt hinter der dreistelligen Zahl angegeben.
Zusammenfassung Wir hoffen Ihnen mit unserem FTP-Workshop einen Einblick in die Vorgehens- und Arbeitsweise eines FTP-Client Programms gegeben zu haben. Mit dem in den beiden Teilen vermittelten Wissen, Befehlen und Funktionen, sollten Sie nun in der Lage sein, Ihren eigenen FTP-Clienten zu programmieren. Einen Ansatz hierfür bekommen Sie, wenn Sie sich unser Demo-Projekt zum FTP-Workshop downloaden. Themen aus Teil 1:
Themen aus Teil 2:
Hinweis zum Abschluss Das Beispielsprojekt zum Teil 2 des FTP-Workshops zeigt, wie man sich mit einem FTP-Server verbindet und sich dann innerhalb des Server-Verzeichnisses bewegen kann (also Verzeichnisse und Dateien anzeigen, inkl. Verzeichniswechsel). Zusätzlich lassen sich Dateien up-/ und downloaden. Dieser Workshop wurde bereits 27.649 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. |
Neu! sevEingabe 3.0 Einfach stark! Ein einziges Eingabe-Control für alle benötigten Eingabetypen und -formate, inkl. Kalender-, Taschenrechner und Floskelfunktion, mehrspaltige ComboBox mit DB-Anbindung, ImageComboBox u.v.m. Tipp des Monats Januar 2025 Dieter Otter Zeilen einer MultiLine-TextBox ermitteln (VB.NET) Dieser Zipp zeigt, wie man die Zeilen einer MultiLine-TextBox exakt so ermitteln kann, wie diese auch in der TextBox dargestellt werden. Access-Tools Vol.1 Über 400 MByte Inhalt Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |