`[[response allHeaderFields] objectForKey: @" Content-Length "]` равно nil? - PullRequest
2 голосов
/ 10 августа 2011

Интересно, при каких условиях объект NSHTTPURLResponse не будет иметь ключ @ "Content-Length"? Это нормально / нормально не иметь этот ключ?

Я пытаюсь что-то с Dropbox SDK, и я понял, что

[[response allHeaderFields] objectForKey:@"Content-Length"]

возвращает nil и приводит к бесконечности downloadProgress:

 NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
    downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength;

Есть ли способ, которым я могу дать ответу этот ключ?

Кстати: это ответ, который я получаю

(gdb) po [response allHeaderFields]
{
    "Cache-Control" = "max-age=0";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/plain; charset=UTF-16LE";
    Date = "Wed, 10 Aug 2011 06:21:43 GMT";
    Etag = 228n;
    Pragma = public;
    Server = dbws;
    "Transfer-Encoding" = Identity;
}

РЕДАКТИРОВАТЬ (в рабочем состоянии):

Как сказал @Mitchell. Серверы не всегда возвращают такой ключ. (Странные DropBox серверы, для png да, для txt файлов иногда нет: /) Итак, для того, чтобы вычислить прогресс загрузки файла, я изменил (основанный на работе) источник:

//In DBRequest.m 
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
    ...
    bytesDownloaded += [data length];
    //start of modification
    //Server might not contain @"Content-Length" key, 
    //in that case use the downloadedBytes. Is better 
    //than having an infinite value because it could
    //be handled by DBRestClient's delegate. (If not 
    //it will have the same effect as infinite)
    if ([response expectedContentLength] == NSURLResponseUnknownLength ) {
        downloadProgress = (CGFloat)bytesDownloaded;
    }else{
        NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
        downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength; 
    }
    //end of modification
    if (downloadProgressSelector) {
        [target performSelector:downloadProgressSelector withObject:self];
    }
}

И так как у меня есть размер файла из метаданных, я могу сделать:

- (void)restClient:(DBRestClient *)client loadProgress:(CGFloat)progress forFile:(NSString *)destPath {
    if (progress > 1) {//Work-around: This means the progress is not a 
        progress = progress/((CGFloat)(metadataOfTheFile.totalBytes));
    }
    ... update the progress bar here
}

Ответы [ 2 ]

3 голосов
/ 10 августа 2011

Если вы помните, что иногда загрузки в Safari или в выбранном вами браузере также не имеют индикатора выполнения, длительность не определяется.В этом конкретном случае лучше всего показать загрузочный счетчик.Это полностью зависит от сервера, возвращающего длину содержимого, что необязательно.

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

Возможно, вам придется искать это свойство в другом месте, но лучшая рекомендация - быть в безопасности, а не сожалеть и избегать всех ошибок NaN.

1 голос
/ 10 августа 2011

Разрешено, чтобы HTTP не имел поля Content-Length, это необязательно.Так что вам нужно справиться с этим:

NSNumber *lengthNumber = [[response allHeaderFields] objectForKey:@"Content-Length"];
NSUInteger contentLength = [lengthNumber unsignedIntegerValue];
if (contentLength == 0) {
    // Calculate progress.
} else {
    // Can't calculate progress.
}
...