When downloading a file, I want to be able to resume the download. For example:
NSFileManager *fm = [NSFileManager defaultManager];
NSString *downloadTempPath = [_tempPath path];
if ([fm fileExistsAtPath:downloadTempPath]) {
// We have a partial download. Get the rest of the file starting at byteCount
NSDictionary *dAttrib = [fm attributesOfItemAtPath:downloadTempPath error:nil];
NSUInteger byteCount = [dAttrib fileSize];
NSLog(@"Preparing to resume download: %@", downloadTempPath);
NSString *requestRange = [NSString stringWithFormat:@"bytes=%d-", byteCount];
[self.request setValue:requestRange forHTTPHeaderField:@"Range"];
}
This will produce a get request with a header like this:
Range:bytes=1000-
I would expect the first 206 response to give me a chunk where I asked it to start, having a header and value like this (dumped from allHeaderFields
):
"Content-Range" = "bytes 1000-340197/340198";
But sometimes it jumps ahead and returns something like this instead:
"Content-Range" = "bytes 32000-340197/340198";
Which is really bad, because I need those bytes from 1000-32000, and it didn't give them to me.
I know that there is no server error, because when I curl to the server it returns the section that I asked for. Also, when I use wireshark, I don't see any packet going to the server. So this is a problem on the iOS side, possibly with the NSURLCache
It appears to be a bug in the NSURLCache
. When I detect that the problem has happened, I do the following and try again.
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:self.request];
Once I have done that, the problem does not happen again. It seems to heal the cache. I saw this on iOS5.0, and since I can no longer reproduce, I don't know if it happens on newer OS'es.