Как отследить ход загрузки веб-содержимого в кодировке gzip? - PullRequest
8 голосов
/ 05 августа 2010

Я пишу клиент для iPhone, который загружает вещи из сети. Поскольку сотовая сеть не такая быстрая, а файлы могут быть большими, я хотел улучшить счетчик активности с помощью индикатора выполнения.

Пока все хорошо, я использую NSURLConnection и проверяю заголовок Content-Length, чтобы увидеть, сколько байтов я скачаю. Затем в обратном вызове -connection:didReceiveData: я добавляю полученные данные к моему NSMutableData объекту, и там я могу отследить размер загруженного контента до ожидаемых байтов.

Это все работает, пока у вас не будет сервера, который поддерживает сжатие GZIP. Сервер, использующий сжатие gzip, будет объявлять x байтов в качестве размера контента. Однако, поскольку NSURLConnection выполняет декомпрессию за кулисами, данные, переданные обратному вызову didReceiveData, уже расширены. Следовательно, ожидаемые загруженные байты меньше, чем фактически полученные байты, в пропорции степени сжатия для файла.

Это означает, что индикатор выполнения переполняется , поскольку ожидаемое количество байтов достигается намного раньше, чем ожидалось. Что-то, что я мог сделать, когда я управляю сервером, это отправить специальные заголовки для содержимого gzip, чтобы избежать распаковки, выполняемой NSURLConnection, но я не могу контролировать все серверы в сети.

Существует ли какой-либо скрытый метод для NSURLConnection, чтобы сообщать о переданных байтах, а не расширенных байтах? Должен ли я кодировать свое собственное NSURLConnection, чтобы отслеживать переданные байты и самостоятельно распаковывать данные gzip для точного индикатора выполнения? Может быть, есть альтернативный базовый API нижнего уровня?

Ответы [ 2 ]

5 голосов
/ 05 августа 2010

IIRC, вы должны использовать -expectedContentLength метод NSURLResponse, который в моем тестировании возвращает NSURLResponseUnknownLength (-1) для сжатого содержимого.

Один из способов - отключить отправкусодержимого gzipped, установив заголовок Accept-Encoding вручную:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:yourURL];
[request setValue:@"" forHTTPHeaderField:@"Accept-Encoding"];

, но, конечно, это лишает смысла содержимое gzipping.: /

(Если есть лучшее решение (которое, как мы надеемся, не предполагает переход на более низкий уровень, чем материал NSURL*), я бы тоже хотел об этом узнать ...)

1 голос
/ 05 августа 2010

Используйте библиотеку ASIHTTPRequest.Это мой общий ответ практически на все вопросы «как мне быть веб-клиентом на iPhone», но в этом случае он особенно полезен.

Проверьте это:

-(void)viewDidLoad {
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:myNSURLObject];
    request.delegate = self;
    request.downloadProgressDelegate = self.myUIProgressViewInstance; 
      //it'll update that progress bar with a percentage complete automatically!
      //or give it any custom class that responds to -progress!
    [request startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    //do whatever to process the data you just got
}

ASIHTTP делаетмногие мощные сетевые операции очень просты.Я большой поклонник.

http://allseeing -i.com / ASIHTTPRequest /

...