Asynchroner SFTP-Upload

Afritus

Mitglied
Hallo Leute,
wie in einem anderen Thema bereits geschrieben, habe ich versucht, eine Datei via SFTP hochzuladen. Das gelingt mir nun einwandfrei (verwende die Library SharpSSH von Tamir Gal).
Nun stehe ich aber vor einem Problem, und zwar blockiert ein Upload größerer Dateien die GUI. Dieses Problem kenne ich schon von der einfachen WebClient-Methode (leider ohne SFTP), da kann man eine Datei mit "Async" ja asynchron hochladen (also kann das Programm während des Uploads andere Sachen erledigen).

Diesen Code verwende ich mit der SharpSSH-Library:

Code:
Private WithEvents transfer As SecureFileTransfer
    Public Event onTransferProgress(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String)
Public Function putFile(ByVal localFile As String, ByVal remotePath As String) As Boolean
        Try
            transfer = New Sftp(Me._hostname, Me._username, Me._password)
            transfer.Connect(Me._port)
            transfer.Put(localFile, remotePath)
            transfer.Close()
            Return True
        Catch ex As Exception
            Debug.Print("Error uploading file: " & ex.ToString)
            Return False
        End Try
    End Function

transfer = New SecureFileTransfer("ftp.server.com", Integer.Parse("22"), user, pass)
        transfer.putFile("test.txt", "/ordner_auf_ftp/" & "text.txt")


Mit folgendem Code lässt sich bei dieser Library sogar feststellen, wie weit der Upload ist:

Code:
Private Sub _onTransferProgress(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String) Handles transfer.onTransferProgress

        ProgressBar1.Maximum = totalBytes
ProgressBar1.Value = transferredBytes

    End Sub


Nun blockiert der Upload aber trotzdem die GUI. Wir kann ich (kostenlos, also nicht mit Rebex und Co.) eine Datei per SFTP hochladen und gleichzeitig eine Blockierung der GUI verhindern (mit Upload-Fortschrittsanzeige)?


MfG und Danke schonmal
 

Shakie

Erfahrenes Mitglied
Ich vermute mal, dass die Put-Methode nicht asynchron ist. Ich konnte leider keine Dokumentation zur SecureFileTransfer-Klasse aus der SharpSSH-Lib finden. Aber vermutlich gibt es eine alternative Methode, die den Upload asynchron startet. Oder sonst musst du einfach einen neuen Thread starten und die Put-Methode daraus starten.
 

Afritus

Mitglied
Danke für die Antwort!
Nein, die Methode ist nicht asynchron. Andere Methoden finde ich leider nicht, ich denke nicht, dass ein asynchroner Upload in dieser Library enthalten ist. Aber das mit dem neuen Thread und der put-Methode klingt interessant. Wie genau funktioniert das? Muss ich dafür die Methode in einem neuen Module/Form starten?
 

Afritus

Mitglied
Vielen Dank, das klappt einwandfrei :)
Nur eine Frage bezüglich des Abbruchs des Backgroundworkers hätte ich noch.
Bei mir wird ja eine Datei hochgeladen, somit wiederholt sich nicht, wie im Video gezeigt, ständig dieselbe Schleife.
Das Cancellation.Pending kann ich also nur nach bzw. vor dem Upload überprüfen, und wenn, dann will ich ja während dem Upload abbrechen.
Wie kann ich das anstellen?
 

Shakie

Erfahrenes Mitglied
Das kann ich dir nicht sagen, vielleicht geht es gar nicht. Du musst nachschauen, ob die SecureFileTransfer-Klasse eine Abbruch-Methode hat (die du threadübergreifend ausführen kannst). Denn das, was bei dir so "lange" dauert, ist die Put-Methode. Wenn die läuft, dann läuft sie halt.
 

Afritus

Mitglied
Ja, die Klasse verfügt tatsächlich über ein Abbrechen-Event. Darauf hätte ich auch selbst kommen können^^
Vielen Dank, funktioniert nun alles.
MfG
 

joerich

Grünschnabel
Hallo,

diese Thema wurde zwar vor längerer Zeit bearbeitet, aber ich versuch es einfach noch mal.

Nach dem ich mich entschieden habe vom normalen FTP-upload zum sftp zu wechseln quäle ich mich mit der Fortschrittsanzeige.


Diese funktioniert mit der Tamir.SharpSsh ohne Backgroundworker auch gut. Allerdings ist ein Programm was nicht mehr reagiert wenn der upload oder download läuft unbrauchbar.
Wenn ich den Backgroundworker nutze bekomme ich folgenden Fehler

der zugriff auf das steuerelement ProgressBar1 erfolgte von einem anderen thread als dem thread, für den er erstellt wurde.

Jetzt hab ich gelesen das man das irgendwie mit invoke hinbekommen soll. Ich selbst bin wohl eher ein scripter als richtiger Programmierer. Deshalb meine Frage wie du das gelöst hast mit dem Abbrechen-Event.

Ziel ist ein uploader über sftp zu bauen den man abbrechen kann und der Fortschritt in irgendeiner Form darzustellen. Vielleicht hat ja jemand eine Klasse gebaut wo das alles drin ist...

Kann jemand helfen?
 

Afritus

Mitglied
Ich beschäftige mich nun eher mit Python, aber die Datei habe ich noch. Musst dir die Stellen selbst raussuchen, aber ich denke, das ist nicht so schwer.

Code:
Imports System.IO
Public Class Form6
    Inherits ComponentFactory.Krypton.Toolkit.KryptonForm
    Private WithEvents transfer As SecureFileTransfer
    Public Event onTransferProgress(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String)

    Public Function IsURLAvail(ByVal sURL As String) As Boolean
        ' Prüft, ob die angegebene URL erreichbar ist
        Try
            Dim oRequest As Net.HttpWebRequest = Net.HttpWebRequest.Create(sURL)

            ' Default-Proxy Einstellungen
            With oRequest
                .Proxy = System.Net.WebRequest.DefaultWebProxy
                .Credentials = System.Net.CredentialCache.DefaultCredentials
            End With

            Dim oResponse As Net.WebResponse = oRequest.GetResponse
            oResponse.Close()

            ' URL ist erreichbar
            Return True
        Catch ex As Exception
            ' URL ist nicht erreichbar
            Return False
        End Try
    End Function
    Shared Function Decryption(ByVal sText As String) As String

        Dim zahlenreihe As String = ""
        Dim alphabet As String = "qewüopgrzntui319adsälö0fhkj246578ycxmbv!""§$%&/()=?-.,;:_'*+#^°<> ßQAYÜÖÄPLMOKNIJBUHVZGCTFXEDRWS"

        For i = 0 To sText.Length - 1
            If alphabet.Contains(sText.Chars(i)) Then
                Dim pos As Integer = alphabet.IndexOf(sText.Chars(i)) - 1
                If zahlenreihe = "" Then
                    zahlenreihe = alphabet.Chars(pos)
                Else
                    zahlenreihe = zahlenreihe + alphabet.Chars(pos)
                End If
            End If
        Next

        Return zahlenreihe

    End Function
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)



        If IsURLAvail("http://www.d3scene-clan.com/") Then

            MsgBox("Ihre Datei wird nun hochgeladen. Bitte haben Sie einen Augenblick Geduld.", vbInformation, "Information")

            Label3.Text = "Datei: " & ListBox1.SelectedItem

            Button1.Enabled = False


            'Background-Worker
            BackgroundWorker1.RunWorkerAsync()


        Else
            MsgBox("Verbindung zu Esport-Masters fehlgeschlagen.", vbCritical, "Fehler")
        End If


    End Sub
    Private Sub _onTransferEnd(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String) Handles transfer.onTransferEnd

        MsgBox("Datei hochgeladen!")

    End Sub
    Private Sub _onTransferStart(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String) Handles transfer.onTransferStart

        ProgressBar1.Maximum = totalBytes

    End Sub
    Private Sub _onTransferProgress(ByVal source As String, ByVal destination As String, ByVal transferredBytes As Integer, ByVal totalBytes As Integer, ByVal message As String) Handles transfer.onTransferProgress

        ProgressBar1.Value = transferredBytes
        Label2.Text = "Fortschritt: " & transferredBytes & " / " & totalBytes & " Bytes"

    End Sub

    Private Sub Form6_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load



        PaletteMode = ComponentFactory.Krypton.Toolkit.PaletteMode.SparkleOrange

        TextBox2.Text = Form2.TextBox1.Text


    End Sub

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        Dim strub As String = Decryption("sptäcäuwbä")
        Dim strpaw As String = Decryption("Yhz3uiäbdrrwztwviuuwz941")


        Try
            transfer = New SecureFileTransfer("ftp.d3scene-clan.com", Integer.Parse("22"), strub, strpaw)
            transfer.putFile("Matches/" & ListBox1.SelectedItem, "/EML-Umbrella/" & TextBox2.Text & "/" & ListBox1.SelectedItem)
        Catch ex As Exception
        End Try

        Dim objFileSystemObject As Object
        Dim deletedir As String = "\umbrella\"
        If System.IO.Directory.Exists(deletedir) Then
            objFileSystemObject = CreateObject("Scripting.FileSystemObject")
            objFileSystemObject.GetFolder("\umbrella\").Delete(True)
            objFileSystemObject = Nothing
        Else

        End If

        Button1.Enabled = True

    End Sub
    Private Sub Form4_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

        If BackgroundWorker1.IsBusy Then

            If MsgBox("Ihre Datei wird noch hochgeladen. Möchten Sie den Upload-Vorgang wirklich abbrechen?", vbQuestion + vbYesNo + vbDefaultButton2, "Information") = vbYes Then
                transfer.cancel()
            Else
                e.Cancel = True
                Exit Sub
            End If
        Else
        End If


    End Sub

    Private Sub Form6_Load_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim Dir As New DirectoryInfo("Matches")
        Dim File As FileInfo

        For Each File In Dir.GetFiles()
            ListBox1.Items.Add(File.Name)
        Next

    End Sub

    Private Sub KryptonButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        If ListBox1.SelectedItem = "" Then
            MsgBox("Bitte wählen Sie eine Datei aus.", vbInformation, "Information")

        Else

            If IsURLAvail("http://www.d3scene-clan.com/") Then

                MsgBox("Ihre Datei wird nun hochgeladen. Bitte haben Sie einen Augenblick Geduld.", vbInformation, "Information")

                Label3.Text = "Datei: " & ListBox1.SelectedItem

                Button1.Enabled = False


                'Background-Worker
                BackgroundWorker1.RunWorkerAsync()


            Else
                MsgBox("Verbindung zu Esport-Masters fehlgeschlagen.", vbCritical, "Fehler")
            End If

        End If

    End Sub

    Shared Sub Show()
        Throw New NotImplementedException
    End Sub

End Class

Mit freundlichen Grüßen,
Markus
 

joerich

Grünschnabel
Danke erstmal, das du die Quellen gesucht und online gestellt hast. Leider ist das Problem noch nicht behoben. Deshalb habe ich ein mini Projekt mit 3 button's erstellt damit es für jeden klarer wird.

1 button hochladen via sftp läuft mit Fortschrittsanzeige (nicht abbrechbar)
2 button backgroundworker läde hoch ohne Fortschrittsanzeige
3 ist der wunsch button der noch nicht geht.

hier zum runterladen. Ich hoffe es kann mir jemand helfen.
Anhang anzeigen sftp_m_backgroundworker.zip