1. Nimm jetzt an unserem Uhans - 3. ADVENT - Gewinnspiel teil - Alle Informationen findest Du hier!

multipart/form POST Upload mit Fortschrittsanzeige unmöglich?

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von mndroid, 12.07.2010.

  1. mndroid, 12.07.2010 #1
    mndroid

    mndroid Threadstarter Neuer Benutzer

    Beiträge:
    12
    Erhaltene Danke:
    7
    Registriert seit:
    29.03.2010
    Ich bin auf ein Problem gestoßen, für das es so ohne weiteres wohl keine Lösung gibt. Jedenfalls habe ich auch nach mehreren Tagen suchen in verschiedensten Foren nichts gefunden:

    Es soll aus einer App heraus ein multipart/form POST Upload gemacht werden. Hierfür habe ich zwei Möglichkeiten gefunden:
    1) Mit HttpURLConnection
    Man baut über URL.openConnection(); eine HttpURLConnection auf, setzt die erforderlichen Parameter, erhält mit HttpURLConnection.getOutputStream() den Stream, in den man die Multipart-Daten schreiben will und durchläuft für die hochzuladene Datei eine Schleife, in der die Daten der Datei abgegriffen und mit einer Puffergröße von bspw. 1 KB in den Stream geschrieben werden.
    Beispiele hierfür gibt es genügend, bspw. hier:
    Yet another blog: Android: How to post file to a php server

    Somit könnte man bspw. alle 1 KB den Fortschritt aktualisieren.
    Das Problem: Android puffert den OutputStream auch dann, wenn man eine Content-Length mitgibt. Die Daten werden also beim Schreiben in den OutputStream noch gar nicht hochgeladen, sondern solange zwischengespeichert, bis die volle Content-Length erreicht ist. Die while-Schleife, die also eigentlich die Daten hochladen soll, ist somit in weniger als einer Sekunde durchlaufen, auch wenn es sich um eine 5MB Datei handelt. Erst mit dem Schreiben des letzten Bytes werden die Daten hochgeladen.
    Die Schleife jedoch ist die einzige Stelle, an der man einen Fortschritt abgreifen kann. Somit fällt diese Möglichkeit leider raus.

    2) Mit der Apache HttpClient 4
    Eine weitere Möglichkeit besteht darin, zwei Bibliotheken von Apache einzubinden und den Upload mit MultipartEntity und HttpClient durchzuführen. Beispiel siehe hier:
    Sam's Technical Blog: Android Multipart upload

    Hier jedoch gibt es das Problem, dass man noch weniger einen Fortschritt abgreifen kann, da der Upload einzig und allein (in einem Rutsch) mit HttpClient.execute(HttpPost) durchgeführt wird und hier überhaupt kein Stream zur Verfügung steht, in dem man Schrittweise den Upload "beobachten" bzw. melden könnte.


    Hat jemand eine Idee, wie man mit Android (>= 1.6) einen Multipart Upload machen UND den Fortschritt des Uploads abgreifen kann?
     
  2. MichaelS, 12.07.2010 #2
    MichaelS

    MichaelS Fortgeschrittenes Mitglied

    Beiträge:
    370
    Erhaltene Danke:
    51
    Registriert seit:
    14.08.2009
    also ich kann mir nicht vorstellen, dass java / android nen buffer voll macht... ich mein, wenn du dateien die größer als dein arbeitsspeicher sind, würde das gesamte system in die kniee gehen ;) ist zwar nun ziemlich groß aber dennoch... der normale vorgang ist halt den output stream sich zu holen und da rein zu puschen und normal geht es auch Realtime... kann mir garnet vorstellen, wie es nicht direkt gesendet werden kann... also ich würde es an deiner stelle mal testen... einfach nen tcp server kurz aufbauen is ja kein akt und nen listener dazu und mal verbinden und daten zu pushen... dan siehst du es ja genau =)

    Also ich würde sage Methode 1 sollte 100% gehen... welche klassen du genau benutzt, weiß ich nicht, da ich es nur von anderen Sprachen so kenne... hab es unter Android nocht nicht benötigt...

    edit: eine suche von 2Sekunden!!! ;) http://stackoverflow.com/questions/254719/file-upload-with-java-with-progress-bar

    gruß
    Micha
     
  3. mndroid, 12.07.2010 #3
    mndroid

    mndroid Threadstarter Neuer Benutzer

    Beiträge:
    12
    Erhaltene Danke:
    7
    Registriert seit:
    29.03.2010
    Leider ist es aber wirklich so, ich denke mir das nicht aus... ;)
    Der Stream wird nochmals intern gepuffert und erst geleert, wenn die Content-Length erreicht ist, oder aber, das hatte ich noch vergessen zu schreiben, spätestens alle 8-12MB. Das ist auch schon mehrfach in Foren berichtet worden, bspw. hier:
    [android-developers] Re: Sending huge files with HttpsUrlConnection??? - AuxOne - com.googlegroups.android-developers - MarkMail

    Und im Debugger sehe ich es ja auch: Die While-Schleife wird bei einem 5MB großen Foto in einer halben Sekunde durchlaufen (der komplette Inhalt wird in den Stream geschrieben. Erst mit dem letzten Bit beginnt der Upload der dann 30 Sekunden oder so dauert.

    /EDIT:
    Hier übrigens noch einmal die Bestätigung von offizieller Seite:
    http://code.google.com/p/android/issues/detail?id=3164#c6

    Wird also für die UrlConnections nach Froyo gefixed, was im Augenblick nichts bringt. Daher die Frage: Welche andere Möglichkeiten gibt es, Dateien per POST als Multipart hochzuladen und den Upload-Fortschritt abzugreifen?
     
    Zuletzt bearbeitet: 13.07.2010
  4. mndroid, 14.07.2010 #4
    mndroid

    mndroid Threadstarter Neuer Benutzer

    Beiträge:
    12
    Erhaltene Danke:
    7
    Registriert seit:
    29.03.2010
    @MichaelS
    Den Link von Stackoverflow kannte ich schon, allerdings habe ich es bisher nie zum Laufen gebracht, da es sich allgemein auf Java bzw. speziell auf die alte HttpClient 3.1 bezieht. Diese war einmal Teil der Android SDK, wurde aber relativ früh wieder entfernt.

    Ich habe es nun noch einmal mit der 4er Version der HttpClient versucht und eine Mischung aus den Wrappern aus dem ersten und dem letzten Post bei Stackoverflow. Dies hat funktioniert und ich kann nun endlich einen Progress bei Multipart Uploads anzeigen lassen.

    Der unschöne Nebeneffekt ist jedoch: Da in der aktuellen Android SDK die HttpClient nur unvollständig übernommen wurde (es fehlen Multipart-Fähigkeiten) muss ich zwei Bibliotheken (apache-mime4j-0.6.jar und httpmime-4.0.1.jar) einbinden. Dadurch ist meine APK von 90KB auf 235KB angewachsen und, noch viel schlimmer, die installierte App-Größe von 175KB auf 732KB. Und das ohne wirklich neue Funktionen zu erhalten (Multipart-Uploads waren ja auch mit Mitteln der Android-SDK möglich), bzw. nur um einen Fortschritt anzeigen zu lassen.

    Das ist wirklich ziemlich ärgerlich. Kennt sonst jemand vielleicht noch eine Möglichkeit, die etwas schlanker ist?

    /EDIT:
    Hier mal ein Beispiel (anhand der Vorlage aus dem Stackoverflow-Link) für einen Wrapper, mit dem man unter Verwendung von HttpClient 4 den Fortschritt eines Uploads abgreifen kann:
     
    Zuletzt bearbeitet: 14.07.2010

Diese Seite empfehlen