I wonder under what conditions an NSHTTPURLResponse object will not have key @”Content-Length” ? Is it usual/normal not to have that key?
I am trying something with the dropbox SDK and I’ve realized that
[[response allHeaderFields] objectForKey:@"Content-Length"]
returns nil and is causing downloadProgress to be infinite:
NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength;
Is there any way I can make the response have that key?
BTW: This is the response I am getting
(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;
}
EDIT (Work-arounded):
As @Mitchell said. Servers not always return such a key. (Weird DropBox servers, for png yes, for txt files sometimes no :/ )
So, in order to calculate the downloadProgress of a file I’ve modified (work-arounded) the source:
//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];
}
}
And since I have the size of a file from the metadata I can do:
- (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
}
If you will recall that sometimes downloads in safari or your browser of choice don’t have a progress bar either, the length isn’t determined. In this particular case a loading spinner is the best thing to show. It entirely depends on the server returning the content-length, which is optional.
I honestly don’t know why it isn’t returning that info, perhaps it’s due to the content-range or some other variable that it decides not to reveal it.
You may have to look elsewhere to obtain that property, but the best recommendation is to be safe, rather than sorry and avoid all NaN errors.