FTP Uploads durch externe Librarys sind nicht immer des Coders lieblinge.
Deshalb habe ich mich entschieden ein Tutorial zu erstellen.
Die Idee kam mir hier [VB 2010] Daten per ftp hochladen
Um nicht lange um den heißen Brei herum zu reden, hier mal der Anfang:
Also..was wir brauchen sind die Namespaces System.Net, Threading und IO.
So weit so gut. Damit kann man jetzt relativ viel anstellen.
Nur noch kein FTP Upload.
Damit wir nun auch Events etc. haben, kommt eine neue Klasse dazu ( FtpState )
Darein kommen nun mehrere Deklarationen.
Die Beschreibung dazu:
wait: Threads über das beginnen des Threads informieren
m_ftprequest: Der FtpWebRequest ( wie WebRequest )
m_filename: Der Dateiname ( auf dem lokalen Dateisystem )
m_operationException: Falls eine Ausnahme auftritt
status: Status ( falls man möchte )
Bei einer Instanzierung braucht man nun eine Methode die das Verwaltet.
Dazu nun auch die Propertys:
Das war auch schon die FTPState-Klasse.
Nun brauchen wir den AsynchronenFtpUploader.
Der Name lässt auf den Klassennamen schließen.
Nun fügen wir ein Event das ProgressChanged-Event ein.
Folgende Methode kann genannt werden wie man möchte. Hier bleibt es "Main".
Dies scheint zu erst ziemlich kompliziert zu sein. Aber alles was es macht, ist die Datei Blockweise auf den Server zu schreiben.
Aber es wird einen Fehler geben. Nämlich "EndGetResponseCallBack ist kein Member von AsynchronousFtpUpLoader".
Das wollen wir nun eleminieren:
Das alles wäre ohne Beispiel jedoch ziemlich dämlich. Deshalb:
Nun. Das wars auch schon. Viel Spass mit dem Code.
Kennzeichnung: keine. Woanders veröffentlichen: nirgendwo, ohne Erlaubnis.
Teile dieses Codes stammen von MSDN.
Modifiziert von: AliveDevil
Geändert: Code auf den zweiten Teil modifiziert und angepasst
Added ListDirectory
Deshalb habe ich mich entschieden ein Tutorial zu erstellen.
Die Idee kam mir hier [VB 2010] Daten per ftp hochladen
Um nicht lange um den heißen Brei herum zu reden, hier mal der Anfang:
Also..was wir brauchen sind die Namespaces System.Net, Threading und IO.
So weit so gut. Damit kann man jetzt relativ viel anstellen.
Nur noch kein FTP Upload.
Damit wir nun auch Events etc. haben, kommt eine neue Klasse dazu ( FtpState )
Darein kommen nun mehrere Deklarationen.
Die Beschreibung dazu:
wait: Threads über das beginnen des Threads informieren
m_ftprequest: Der FtpWebRequest ( wie WebRequest )
m_filename: Der Dateiname ( auf dem lokalen Dateisystem )
m_operationException: Falls eine Ausnahme auftritt
status: Status ( falls man möchte )
Bei einer Instanzierung braucht man nun eine Methode die das Verwaltet.
Dazu nun auch die Propertys:
VB.NET-Quellcode
- Public ReadOnly Property OperationComplete() As ManualResetEvent
- Get
- Return wait
- End Get
- End Property
- Public Property Request() As FtpWebRequest
- Get
- Return m_request
- End Get
- Set(ByVal value As FtpWebRequest)
- m_request = value
- End Set
- End Property
- Public Property FileName() As String
- Get
- Return m_filename
- End Get
- Set(ByVal value As String)
- m_filename = value
- End Set
- End Property
- Public Property OperationException() As Exception
- Get
- Return m_operationException
- End Get
- Set(ByVal value As Exception)
- m_operationException = value
- End Set
- End Property
- Public Property StatusDescription() As String
- Get
- Return status
- End Get
- Set(ByVal value As String)
- status = value
- End Set
- End Property
Das war auch schon die FTPState-Klasse.
Nun brauchen wir den AsynchronenFtpUploader.
Der Name lässt auf den Klassennamen schließen.
Nun fügen wir ein Event das ProgressChanged-Event ein.
Folgende Methode kann genannt werden wie man möchte. Hier bleibt es "Main".
VB.NET-Quellcode
- Public Property localfile As String
- Public Property ftpfile As String
- Public Property user As String
- Public Property password As String
- ''' <summary>
- ''' Methode bei neu Erstellung
- ''' </summary>
- ''' <param name="localfile">Die Lokale Datei. Kein file:/// sondern einfach ordner/datei.ext</param>
- ''' <param name="ftpfile">Die Datei auf dem Server. Zusammenbau: ftp://host:port/ordner/datei.ext</param>
- ''' <param name="user">Der Benutzername</param>
- ''' <param name="password">Das Passwort</param>
- ''' <remarks></remarks>
- Public Sub New(ByVal localfile As String, ByVal ftpfile As String, ByVal user As String, ByVal password As String)
- Me.localfile = localfile
- Me.ftpfile = ftpfile
- Me.user = user
- Me.password = password
- End Sub
- ''' <summary>
- ''' Starte den Upload
- ''' </summary>
- ''' <remarks></remarks>
- Public Sub Upload()
- Dim waitObject As ManualResetEvent
- Dim target As New Uri(localfile) ' Erstelle eine neue URI. Bei nicht richtigem Gebrauch: Exception
- Dim fileName As String = ftpfile ' Lokale Datei
- Dim state As New FtpState() ' Initialisiere neue Instanz von FtpState
- Dim request As FtpWebRequest = DirectCast(WebRequest.Create(target), FtpWebRequest) ' Erstelle einen neuen FtpWebRequest auf Basis des targets
- request.Method = WebRequestMethods.Ftp.UploadFile ' Hochladen!
- request.Credentials = New NetworkCredential(user, password) ' Login Daten
- state.Request = request ' schreibe den Request in den FtpState
- state.FileName = fileName ' schreibe den Dateinamen in den FtpState
- waitObject = state.OperationComplete ' kopiere das ManualResetEvent in das waitObject
- Dim requestStream As Stream = Nothing ' neuen Stream erstellen
- Try ' Eventuelle Fehler abfangen
- requestStream = request.GetRequestStream() ' kopiere den Stream in den RequestStream
- Const bufferLength As Integer = 2048 ' Pufferlänge. Kann angepasst werden.
- Dim buffer As Byte() = New Byte(bufferLength - 1) {} ' Neues Array von Byte mit der Länge von bufferLength erstellen
- Dim count As Integer = 0 ' für ProgressChanged wichtig!
- Dim readBytes As Integer = 0 ' gelesene Bytes
- Dim totalBytes As Integer = CInt(New FileInfo(state.FileName).Length) ' totale Anzahl der Bytes in der Datei
- Dim stream As FileStream = File.OpenRead(state.FileName) ' Datei zum lesen öffnen
- Do
- readBytes = stream.Read(buffer, 0, bufferLength) ' lese in buffer von Index 0 die nächsten bufferLength-Bytes
- requestStream.Write(buffer, 0, readBytes) ' schreibe die Datei auf dem Server
- count += readBytes ' addiere readBytes zu count hinzu
- RaiseEvent UploadFileProgressChanged(totalBytes, count) ' wirf das Event ProgressChanged
- Loop While readBytes <> 0 ' solange readBytes nicht 0
- requestStream.Close() ' schließe den Stream
- state.Request.BeginGetResponse(New AsyncCallback(AddressOf EndGetResponseCallBack), state) ' Bekomme eine Antwort
- Catch e As Exception
- state.OperationException = e ' Exception zugänglich machen
- state.OperationComplete.[Set]() ' Fertig.
- Return ' Abbrechen
- End Try
- If state.OperationException IsNot Nothing Then
- Throw state.OperationException
- End If
- End Sub
Dies scheint zu erst ziemlich kompliziert zu sein. Aber alles was es macht, ist die Datei Blockweise auf den Server zu schreiben.
Aber es wird einen Fehler geben. Nämlich "EndGetResponseCallBack ist kein Member von AsynchronousFtpUpLoader".
Das wollen wir nun eleminieren:
VB.NET-Quellcode
- Private Sub EndGetResponseCallBack(ByVal ar As IAsyncResult)
- Dim state As FtpState = DirectCast(ar.AsyncState, FtpState) ' Konvertiere den IAsyncResult in einen FtpState
- Dim response As FtpWebResponse = Nothing ' Neuen FtpWebResponse erstellen
- Try
- response = DirectCast(state.Request.EndGetResponse(ar), FtpWebResponse) ' konvertiere den EndGetResponse in einen FtpWebResponse
- response.Close() ' schließen
- state.StatusDescription = response.StatusDescription ' Status beschreiben
- state.OperationComplete.[Set]() ' Fertig.
- Catch e As Exception ' Fehler abfangen
- state.OperationException = e ' zugänglich machen
- state.OperationComplete.[Set]() ' Fertig.
- End Try
- End Sub
Das alles wäre ohne Beispiel jedoch ziemlich dämlich. Deshalb:
VB.NET-Quellcode
- Sub Upload(ByVal dest_file As String, ByVal src_file As String)
- Dim ftpClient As New AsynchronousFtpUploader ' Neuer Uploader
- Dim FTPHost As String = "localhost" ' Der Host
- Dim FTPPort As Integer = 21 ' Der Port
- Dim FTPPath As String = "/ordner" ' Der Pfad
- Dim FTPUser As String = "anonymous" ' Der User
- Dim FTPPasswd As String = "" ' Das Passwort für den FTPUser
- AddHandler ftpClient.UploadFileProgressChanged, AddressOf UploadFileProgressChanged ' Füge neuen Handler hinzu
- ftpclient.Main("ftp://" & FTPHost & ":" & FTPPort & If(FTPPath.StartsWith("/"), "", "/") & FTPPath & If(FTPPath.EndsWith("/"), "", "/") & dest_file, src_file, FTPUser, FTPPasswd) ' Korrekte Konvertierung^^ und Start des Uploads
- End Sub
- Sub UploadFileProgressChanged(ByVal total As Long, ByVal done As Long)
- ' Progress wurde geändert!
- End Sub
Nun. Das wars auch schon. Viel Spass mit dem Code.
Kennzeichnung: keine. Woanders veröffentlichen: nirgendwo, ohne Erlaubnis.
Teile dieses Codes stammen von MSDN.
Modifiziert von: AliveDevil
Geändert: Code auf den zweiten Teil modifiziert und angepasst
Added ListDirectory
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „AliveDevil“ ()