Ich schreibe einen iPhone-Client, der Sachen aus dem Netz herunterlädt. Da das Mobilfunknetz nicht so schnell ist und Dateien sehr groß sein können, wollte ich den Aktivitätsbereich mit einem Fortschrittsbalken verbessern.
Soweit so gut, benutze ich NSURLConnection und überprüfe den Header Content-Length
, um zu sehen, wie viele Bytes ich herunterladen werde. Dann füge ich im -connection:didReceiveData:
-Rückruf empfangene Daten an mein NSMutableData
-Objekt an und dort kann ich die Größe des heruntergeladenen Inhalts bis zu den erwarteten Bytes verfolgen.
Das funktioniert so lange, bis Sie einen Server haben, der die gzip-Komprimierung unterstützt. Ein Server, der gzip-Komprimierung verwendet, wird x-Bytes als die Größe des Inhalts ankündigen. Da NSURLConnection jedoch die Dekomprimierung im Hintergrund ausführt, sind die Daten, die an den didReceiveData
-Rückruf übergeben werden, bereits erweitert. Daher sind die erwarteten heruntergeladenen Bytes kleiner als die tatsächlich empfangenen Bytes im Verhältnis des Komprimierungsverhältnisses für die Datei.
Dies bedeutet, dass der Fortschrittsbalken überläuft , da die Anzahl der erwarteten Bytes viel früher als erwartet erreicht wird. Etwas, was ich tun könnte, wenn ich den Server kontrolliere, wäre, spezielle Header für den gzip-Inhalt zu senden, um die Dekomprimierung durch NSURLConnection zu vermeiden, aber ich kann nicht alle Server im Web kontrollieren.
Gibt es eine versteckte Methode für NSURLConnection, um die übertragenen Bytes und nicht die erweiterten Bytes zu melden? Muss ich meine eigene NSURLConnection codieren, um übertragene Bytes zu verfolgen, und die gzip-Daten selbst für einen genauen Fortschrittsbalken-Indikator dekomprimieren? Vielleicht gibt es eine alternative Core Foundation API auf niedrigerer Ebene?
Verwenden Sie die ASIHTTPRequest-Bibliothek. Das ist meine generische Antwort auf so ziemlich alle "Wie bin ich ein Web-Client auf dem iPhone" Fragen, aber es ist in diesem Fall besonders nützlich.
Überprüfen Sie dies:
%Vor%ASIHTTP macht viele leistungsstarke Netzwerkoperationen sehr einfach. Ich bin ein großer Fan.
IIRC, Sie sollten die -expectedContentLength
-Methode von NSURLResponse
verwenden, die bei meinen Tests NSURLResponseUnknownLength
(-1) für gzipierten Inhalt zurückgibt.
Eine Problemumgehung wäre, das Senden von gezippten Inhalten zu deaktivieren, indem Sie den Header Accept-Encoding
: manuell setzen:
Aber natürlich wird dadurch der Inhalt des Inhalts verloren. : /
(Wenn es eine bessere Lösung gibt (die hoffentlich nicht tiefer geht als das NSURL*
Zeug), würde ich es auch gerne wissen ...)
Tags und Links objective-c iphone nsurlconnection gzip