FTP Client

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Trade.

    Guten Abend Gemeinde,

    Ich schreibe gerade für die Schule einen FTP Clienten, dieser Funktioniert eigentlich auch schon einwandsfrei, dennoch möchte ich noch so einige detail's anbringen.
    Allerdings beweg ich mich da etwas im dunkeln, es würde mich sehr freuen wenn ihr mir ein paar Tipps geben könntet =)

    hier der Komplette Sourcecode :
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Net
    2. Imports System.IO
    3. Public Class Form1
    4. Private Sub listFTP(ByVal URL As String, ByVal bk As String, ByVal pw As String)
    5. Dim requ As FtpWebRequest = Nothing
    6. Dim resp As FtpWebResponse = Nothing
    7. Dim reader As StreamReader = Nothing
    8. Try
    9. requ = CType(WebRequest.Create(URL), FtpWebRequest)
    10. requ.Credentials = New NetworkCredential(bk, pw)
    11. requ.Method = WebRequestMethods.Ftp.ListDirectory
    12. resp = CType(requ.GetResponse(), FtpWebResponse)
    13. reader = New StreamReader(resp.GetResponseStream())
    14. Do While (reader.Peek() > -1)
    15. ListBox1.Items.Add(reader.ReadLine())
    16. Loop
    17. ToolStripStatusLabel1.Text = "Auflistung Komplett"
    18. Catch ex As UriFormatException
    19. ToolStripStatusLabel1.Text = ex.Message
    20. Catch ex As WebException
    21. ToolStripStatusLabel2.Text = ex.Message
    22. Finally
    23. If reader IsNot Nothing Then reader.Close()
    24. End Try
    25. End Sub
    26. Private Sub downloadFTP(ByVal URL As String, ByVal bk As String, ByVal pw As String)
    27. Dim requ As FtpWebRequest = Nothing
    28. Dim resp As FtpWebResponse = Nothing
    29. Dim respStrm As Stream = Nothing
    30. Dim fileStrm As FileStream = Nothing
    31. Try
    32. requ = CType(WebRequest.Create(URL), FtpWebRequest)
    33. requ.Credentials = New NetworkCredential(bk, pw)
    34. requ.Method = WebRequestMethods.Ftp.DownloadFile
    35. resp = CType(requ.GetResponse(), FtpWebResponse)
    36. respStrm = resp.GetResponseStream()
    37. SaveFileDialog1.FileName = Path.GetFileName(requ.RequestUri.LocalPath)
    38. If (SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK) Then
    39. fileStrm = File.Create(SaveFileDialog1.FileName)
    40. Dim buff(1024) As Byte
    41. Dim bytesRead As Integer = 0
    42. Do While (True)
    43. bytesRead = respStrm.Read(buff, 0, buff.Length)
    44. If (bytesRead = 0) Then Exit Do
    45. fileStrm.Write(buff, 0, bytesRead)
    46. Loop
    47. ToolStripStatusLabel1.Text = "Downlad komplett"
    48. End If
    49. Catch ex As UriFormatException
    50. ToolStripStatusLabel1.Text = ex.Message
    51. Catch ex As WebException
    52. ToolStripStatusLabel2.Text = ex.Message
    53. Catch ex As IOException
    54. ToolStripStatusLabel2.Text = ex.Message
    55. End Try
    56. End Sub
    57. Private Sub uploadFTP(ByVal fileName As String, ByVal URL As String, ByVal bk As String, ByVal pw As String)
    58. Dim requ As FtpWebRequest = Nothing
    59. Dim resp As FtpWebResponse = Nothing
    60. Dim requStrm As Stream = Nothing
    61. Dim fileStrm As FileStream = Nothing
    62. Try
    63. requ = CType(WebRequest.Create(URL), FtpWebRequest)
    64. requ.Credentials = New NetworkCredential(bk, pw)
    65. requ.Method = WebRequestMethods.Ftp.UploadFile
    66. requ.Timeout = System.Threading.Timeout.Infinite
    67. requ.Proxy = Nothing
    68. requStrm = requ.GetRequestStream()
    69. Dim buff(20480) As Byte
    70. Dim bytesRead As Integer = 0
    71. fileStrm = File.OpenRead(fileName)
    72. Do While (True)
    73. bytesRead = fileStrm.Read(buff, 0, buff.Length)
    74. If (bytesRead = 0) Then Exit Do
    75. requStrm.Write(buff, 0, bytesRead)
    76. Loop
    77. requStrm.Close()
    78. resp = CType(requ.GetResponse(), FtpWebResponse)
    79. ToolStripStatusLabel1.Text = "Upload Komplett"
    80. Catch ex As UriFormatException
    81. ToolStripStatusLabel1.Text = ex.Message
    82. Catch ex As IOException
    83. ToolStripStatusLabel2.Text = ex.Message
    84. Catch ex As WebException
    85. ToolStripStatusLabel2.Text = ex.Message
    86. Finally
    87. If resp IsNot Nothing Then resp.Close()
    88. If fileStrm IsNot Nothing Then fileStrm.Close()
    89. If requStrm IsNot Nothing Then requStrm.Close()
    90. End Try
    91. End Sub
    92. Private Sub deleteFTP(ByVal URL As String, ByVal bk As String, ByVal pw As String)
    93. Dim requ As FtpWebRequest = Nothing
    94. Dim resp As FtpWebResponse = Nothing
    95. Try
    96. requ = CType(WebRequest.Create(URL), FtpWebRequest)
    97. requ.Credentials = New NetworkCredential(bk, pw)
    98. requ.Method = WebRequestMethods.Ftp.DeleteFile
    99. resp = CType(requ.GetResponse(), FtpWebResponse)
    100. ToolStripStatusLabel1.Text = "Datei wurde gelöscht!"
    101. Catch ex As UriFormatException
    102. ToolStripStatusLabel1.Text = ex.Message
    103. Catch ex As WebException
    104. ToolStripStatusLabel2.Text = ex.Message
    105. Finally
    106. If resp IsNot Nothing Then resp.Close()
    107. End Try
    108. End Sub
    109. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    110. ToolStripStatusLabel1.Text = ""
    111. ToolStripStatusLabel2.Text = ""
    112. lbSave.Hide()
    113. End Sub
    114. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    115. lbSave.Text = ""
    116. ListBox1.Items.Clear()
    117. lbSave.Text = tbURL.Text
    118. listFTP(tbURL.Text, tbUsername.Text, tbPassword.Text)
    119. End Sub
    120. Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
    121. tbURL.Text = lbSave.Text
    122. tbURL.Text &= ListBox1.SelectedItems(0).ToString
    123. End Sub
    124. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    125. downloadFTP(tbURL.Text, tbUsername.Text, tbPassword.Text)
    126. End Sub
    127. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    128. If (OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK) Then
    129. uploadFTP(OpenFileDialog1.FileName, tbURL.Text & Path.GetFileName(OpenFileDialog1.FileName), tbUsername.Text, tbPassword.Text)
    130. End If
    131. End Sub
    132. Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    133. If (MessageBox.Show("Wollen Sie die Datei wirklich löschen?", "Achtung", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) = Windows.Forms.DialogResult.Yes) Then
    134. deleteFTP(tbURL.Text, tbUsername.Text, tbPassword.Text)
    135. End If
    136. End Sub
    137. End Class


    Meine fragen dazu sind folgende:
    • Wen ich damit eine grössere Datei downloade, friert meine form ein und lässt sich weder minimieren noch verschieben bis der download abgeschlossen wurde. Dies ist natürlich recht nervig. kann ich dies irgendwie verhindern?
    • gibt es irgend eine Möglichkeit, die grösse der Bytes die schon heruntergeladen wurden anzuzeigen (zb. ProgressBar oder in Labels)
    • und mir ist aufgefallen, das die Download Rate sehr klein ist, ist es möglich diese zu vergrössern, oder gar ohne Begrenzung zuhaben?

    Ich hoffe das einige von euch da draußen mir da etwas behilflich sein könnten.

    Mfg RajYuJin
    Moin,

    ich würde an Deiner Stelle folgendes machen:
    • Methoden- und Parameternamen guidelinekonform machen: msdn.microsoft.com/de-de/library/ms229002(v=vs.110).aspx
    • Using-Blöcke verwenden
    • Die Möglichkeit hinzufügen, Passwörter auch als SecureString zu behandeln, der Konstruktion der NetworkCredential-Klasse hat viele Überladungen, die diese u. a. auch gleich annehmen.
    • SSL-Unterstützung. FTP ist total unsicher und sollte nicht mehr benutzt werden, stattdessen lieber FTPS. Du kannst das beim FtpWebRequest mit EnableSsl einstellen.
    • Controls und Forms bzw. Klassen einen richtigen Namen geben, der ebenfalls guidelinekonform ist (s. o.)
    • Das in eine Klasse auslagern oder gar eine DLL, damit es abstrakter ist und Du nicht direkt die Controls ansprichst.
    • OpenFileDialog noch disposen (siehe Using-Block). Also einfach alles, was IDisposable implementiert. Wenn Du VS (2013) Professional nutzt, dann kannst Du das mit der Codeanalyse rausfinden, ansonsten halt manuell MSDN abklappern.

    RajYuJin schrieb:

    Wen ich damit eine grössere Datei downloade, friert meine form ein und lässt sich weder minimieren noch verschieben bis der download abgeschlossen wurde. Dies ist natürlich recht nervig. kann ich dies irgendwie verhindern?

    Ja, dazu musst Du die Methode asynchron ausführen. Siehe Thread, ThreadPool oder Task. Vielleicht kannst Du, wenn Du mit .NET 4.0 arbeitest sogar async und await verwenden.

    RajYuJin schrieb:

    gibt es irgend eine Möglichkeit, die grösse der Bytes die schon heruntergeladen wurden anzuzeigen (zb. ProgressBar oder in Labels)

    Ob das beim FtpWebRequest so geht, weiß ich nicht. Ich würde das sowieso alles über einen TcpClient lösen und dann beim Lesen einfach für jedes Byte eine Value inkrementieren, die dann in der Formel benutzt wird, also à la (readBytes / totalBytes) * 100.
    Zudem hätte man damit weitaus mehr Möglichkeiten als hier und könnte auch eigene Befehle ausführen usw.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Besten dank für die Konstruktiven Ideen, und Ratschlägen.

    ich werde die ganzen Ratschläge und Hilfestellungen, versuchen zuverstehn und umzusetzen, werde allerdings erst morgen dazu kommen,
    werde danach berichten.

    Cheers
    Welche Methode benutzt Du denn jetzt? Noch den ​FtpWebRequest?

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Naja, für Downloads würde ich auch kein FTPS, sondern HTTP(S) verwenden, das ist einfach das Protokoll dafür, basiert auch auf TCP.
    Schaue Dir mal den WebClient an, damit geht es dann sicher schneller.

    Falls der auch etwas spinnt, setzt Du da einfach bei der Instanz dann Proxy auf Nothing und das sollte gut laufen.
    Wie man etwas via HTTP(S) downloaded solltest Du ja wissen, einfach die URL abrufen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Auch wenn ich nicht weiß wie unterschiedlich die Geschwindigkeiten in der Praxis letztendlich aussehen werden, klingt es schon reichlich paradox, eine Datei mit dem HYPERTEXT Transfer Protocol zu übertragen anstatt mit dem FILE Transfer Protocol :D

    Möchte deinen Tipp nicht anzweifeln, ist mir nur gerade so durch den Kopf geschwirrt ^^
    Als du den Webinstaller für VB bzw. VS runtergeladen hast, wirst du zu 100000% auch das Hypertext Transfer Protocol verwendet haben und nicht das File Transfer Protocol ;)
    Viele Frauen kamen, viele sind gegangen, eine ist geblieben 12.5.12 <3 ich liebe dich Schatz :love: :love:
    Ja, natürlich, FTP wurde 1985 spezifiziert und damals ging es vermutlich nur daran, über irgendein vermutlich kleineres Netzwerk Dateien auszutauschen. Und im Jahre 1991, als dann HTTP kam, ging es vermutlich auch in erster Linie darum, dass Webserver Websites (eben Hypertext) über große Teile des Globus verteilen. Darüber Dateien zu veschicken, spielte wohl erst viel später eine Rolle, eben als man auch größere Datenmengen übertragen konnte.

    Aber so entstanden nunmal diese Namensgebungen, die dazu führen, dass immer noch Leute meinen, Dateien im Internet müssten natürlich über das File Transfer Protocol übertragen werden.
    @lukekogv Paradox ist dies nicht, FTP ist unsicher, wenn dann mit FTPS. HTTP(S) basiert auf TCP und damit kann man wunderbar Daten herunterladen, machst Du in Deinem Browser auch andauernd. Genau dafür ist es ja auch da, deshalb sollten imo FTP-Downloads eher vernachlässigt werden.
    Grade Leute, die von außen Zugriff auf etwas haben sollen, müssten dann unbedingt HTTP(S) verwenden, weil über FTP(S) hätten die ja irgendwo dann Deine Zugagsdaten, was wenig sinnvoll und unsicher ist.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

    Guten Tach Gemeinde, versuche den Download nun via WebClient, das schaut nun so aus.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim WithEvents client As New Net.WebClient
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. client.Credentials = New Net.NetworkCredential("Username", "Password")
    5. Try
    6. client.DownloadDataAsync(New Uri("ftp://blablalink\test.rar"), "C:\test.rar")
    7. Catch ex As Exception
    8. MsgBox("Fehler")
    9. End Try
    10. End Sub
    11. Sub DownloadStateChanged(ByVal sender As System.Object, ByVal e As System.Net.DownloadProgressChangedEventArgs) Handles client.DownloadProgressChanged
    12. ProgressBar1.Value = e.ProgressPercentage
    13. End Sub
    14. End Class


    nun funktioniert zwar die anzeige der Progressbar, jedoch wird nicht wirklich was heruntergeladen, bzw, gespeichert im angegebenen Zielort. Und wen ich eine Datei, ca. 1.5 GB runterladen möchte, passiert einfach gar nichts, bei widerholtem drücken des Buttons krieg ich dann die Fehlermeldung.

    Kann mir jemand sagen an was des liegt?

    PS:
    ​weil über FTP(S) hätten die ja irgendwo dann Deine Zugagsdaten, was wenig sinnvoll und unsicher ist.

    wen vom Server aus, nur lesezugriff gestattet ist, sollte dies aber keine Probleme darstellen, oder?


    Du benutzt immer noch FTP, Du sollst aber doch HTTP(S) nutzen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Trade schrieb:

    Du benutzt immer noch FTP, Du sollst aber doch HTTP(S) nutzen.

    Grüße


    Das liegt daran das die Daten auch auf nem FTP Server liegen, und der Inhaber des Roots, keinen Webspace anlegen möchte, daher bin ich gezwungen bei ftp zubleiben.

    Deshalb steh ich immer noch vor den obengenannten Problemen.

    Grüsse
    Achso ok, dann ist das was anderes. Nun gut, ich habe da eine Vermutung, warum es nicht geht.
    Setze mal das DownloadDataCompleted-Event und schaue mal, ob e.Error einen Inhalt hat. Ich tippe darauf, dass Du keinen Zugriff auf C:\ hast und das Ganze somit fehlschlägt.

    Setze außerdem noch client.Proxy = Nothing, somit solltest Du beim Downloaden sonst keine Probleme mehr haben.
    Ich sehe außerdem ja gerade, dass das ein purer FTP-Client werden soll, dann bist Du nat. auf FTP-only angewiesen und es geht ja nur dann um den Nutzer selbst, wenn er es bedient, wobei FTP nach wie vor unsicher ist und Du FTPS verwenden solltest.
    Da Du ja keinen TcpClient hast, wo Du einfach AUTH TLS an den Server schicken könntest, musst Du halt beim WebClient schauen, wie Du das hinkriegen könntest. ;)

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    besten dank, für deine Rasche Antwort. =)

    ich hab den fehler gefunden und zwar war des

    VB.NET-Quellcode

    1. client.DownloadDataAsync​
    musste durch

    VB.NET-Quellcode

    1. ​client.DownloadFileAsync
    ersetzt werden.. irgendwie logisch.. sry^^
    Jo, das auch, stimmt. Somit ist es halt direkt die Datei, ansonsten wären es ja nur die Bytes.
    Aber somit weißt Du wenigstens, wie Du Fehler behandeln kannst. ;)

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: