Android Tutorial Android FTP Tutorial

klaus

Expert
Licensed User
Longtime User
Dieses Tutorial deckt die offizielle FTP-Library.
Die FTP-Library ist auf Apache Commons Net basiert.

Das Android OS erlaubt es uns, die Entwickler, nicht den Haupt-Thread für mehr als 5 Sekunden zu blockieren. Wenn der Haupt-Thread zu lange beschäftigt ist, und nicht in der Lage ist die Anwender-Events zu behandeln, erscheint die Meldung "Application not responding".
Deshalb sollten langsame Operationen wie Netzwerk-Operationen im Hintergrund durchgeführt werden.
Die FTP- Library ist folgender Weise aufgebaut. Alle Methoden gehen sofort zurück. Wenn eine Aufgabe (task) abgeschlossen ist wird ein Event ausgelöst. In der Tat kann man mehrere Aufgaben eine nach der anderen übermitteln. Das FTP-Protokoll unterstützt nur eine einzelne Aufgabe zur gleichen Zeit, so daß die Aufgaben seriell verarbeitet werden.

Die Benutzung der FTP-Library ist sehr einfach.
Der erste Schritt ist das FTP-Objekt zu initialisieren. Wenn dies ein Activity-Modul ist, dann muss man es in Activity_Create tun, wenn FirstTime True ist.
Für Service-Modulen muss es in Service_Create initialisiert werden.

B4X:
Sub Process_Globals
    Dim FTP As FTP
End Sub
Sub Globals
End Sub
Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        FTP.Initialize("FTP", "ftp.example.com", 21, "user", "password")
    End If
FTP.Initialize verbindet nicht mit dem Server. Die Verbindung wird implizit mit der nächsten Aufgabe (task) eingerichtet werden.

Download (herunterladen)

Das Herunterladen einer Datei wird durch den Aufruf von DownloadFile erzeugt, mit dem Remote-Datei-Pfad (remote file path ) und dem Lokalen-Datei-Pfad (local file path).
Wenn Sie den Download-Fortschritt anzeigen wollen, dann sollten Sie das DownloadProgress Event behandeln.
Wenn der Download abgeschlossen ist, wird das DownloadCompleted Event ausgelöst. Die ServerPath wird als erster Parameter an alle Events übergeben. Sie können es verwenden, um zwischen verschiedenen Aufgaben (tasks) zu unterscheiden. Achten Sie darauf, den Success Parameter zu überprüfen. Wenn Success False ist, dann können Sie die Ausnahme Nachricht (exception message) durch den Aufruf von LastException finden.
B4X:
    FTP.DownloadFile("/somefolder/files/1.zip", False, File.DirRootExternal, "1.zip")
 
Sub FTP_DownloadProgress (ServerPath As String, TotalDownloaded As Long, Total As Long)
    Dim s As String
    s = "Downloaded " & Round(TotalDownloaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub
Sub FTP_DownloadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub
Upload (Hochladen)

Uploading ist ähnlich wie downloading.
B4X:
    FTP.UploadFile(File.DirRootExternal, "1.txt", True, "/somefolder/files/1.txt")
Sub FTP_UploadProgress (ServerPath As String, TotalUploaded As Long, Total As Long)
    Dim s As String
    s = "Uploaded " & Round(TotalUploaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub
Sub FTP_UploadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub

List files and folders (Dateien Liste und Pfade)

FTP.List sendet eine Anforderung (request) für die Liste der Dateien und Ordner in einen bestimmten Pfad.
Das ListCompleted-Event wird ausgelöst, wenn die Daten verfügbar sind.
Sie können einen Code verwenden, ähnlich dem folgenden, um weitere Informationen über die Einträge zu bekommen:

B4X:
FTP.List("/")
...
Sub FTP_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, Files() As FTPEntry)
    Log(ServerPath)
    If Success = False Then
        Log(LastException)
    Else
        For i = 0 To Folders.Length - 1
            Log(Folders(i).Name)
        Next
        For i = 0 To Files.Length - 1
            Log(Files(i).Name & ", " & Files(i).Size & ", " & DateTime.Date(Files(i).Timestamp))
        Next
    End If
End Sub
Delete (Löschen)

Löschen wird durch den Aufruf von FTP.Delete mit dem vollständigen Pfad erfolgen. Hier auch, wenn die Aufgabe abgeschlossen ist wird ein Event (DeleteCompleted) ausgelöst.

Closing the connection (Verbindung abschließen)

Sie können die Verbindung schließen, indem Sie FTP.Close aufrufen. Close wird auf den Abschluss der anderen Aufgaben warten, und dann die Verbindung schließen. Dies geschieht im Hintergrund.
FTP.CloseNow schließt die Verbindung sofort ab, die verbleibenden Aufgaben werden verlassen.

Einige Hinweise:
- Zu jeder Zeit dürfen nicht mehr als 15 Aufgaben (tasks) warten. Andernfalls erhalten Sie eine RejectedExecutionException (dies geschieht, wenn das interne Thread Pool (internal threads pool) überfordert ist).
- Die Reihenfolge der erledigten Aufgaben kann anders sein als die der Reihenfolge der Übergabe.
- Die AsciiFile Parameter setzen den File-Transfer-Modus. Wenn AsciiFile True ist, dann wird jedes 'Ende der Zeile-Zeichen' (end of line character) auf das 'Ende der Zeile-Zeichen' des Servers übersetzt. Wenn Ihr FTP-Server Unix oder Linux ist dann ist das Ende der Zeile Zeichen das gleiche wie in Android.
In den meisten Fällen können Sie AsciiFile auf False gesetzt.

Die Library steht hier zum Herunterladen zur Verfügung: http://www.b4x.com/forum/addit...html#post57944
 
Last edited:

Roeschti

Member
Licensed User
Longtime User
Kleine Anmerkung

Ich erlaube mir einfach hier einen kleinen Erfahrungwert mitzuteilen, für die Nächsten die darüber stolpern...und zwar ist die Sub FTP_DownloadProgress relativ nutzlos. Ich habe noch keinen FTP Server gefunden, der die notwendigen Werte korrekt bzw. überhaupt zurück gibt.

Folgender Weg ist bedeutend einfacher und vorallem zuverlässiger:

Einen Timer erstellen, der etwa alle halbe Sekunde ein Tick auslöst und veilleicht eine Progressbar, sieht schöner aus als eine nackte Prozent-Angabe :)


Beim einlesen der Files zB mit FTP_ListCompleted sollte man sich in der Schlaufe die Dateinamen und deren Grösse merken zB in einer List oder Map.

Beim downloaden eines Files den Timer starten. Im Tick Event die lokale Dateigrösse auslesen und vergleichen mit der File-Grösse aus der List / Map. In meinem folgenden Beispiel ist diese Grösse in einer Variable (lngFSize), da sie von einer anderen Sub aufbereitet wird:


B4X:
Sub tmrDL_Tick
   DoEvents
   Dim lngSize As Long
   'Aktuelle Grösse ermittlen 
   lngSize = File.Size(strLocalDir,strLocalFile)
   DoEvents
        'Progressbar aktualisieren
   intProgress = Round(100 / lngFSize * lngSize)
   pbDL.Progress = intProgress
   'If intProgress = 100 Then tmrDL.Enabled = False
   DoEvents
End Sub
 
Top