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

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

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

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

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

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

9
задан Mike Abdullah 27 January 2012 в 21:11
поделиться

2 ответа

Используйте библиотеку 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/

1
ответ дан 4 December 2019 в 23:38
поделиться

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

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

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

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

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

5
ответ дан 4 December 2019 в 23:38
поделиться