I've encountered a problem using AFNetworking to download files from a Rackspace repository.
Basically sometimes the file is not completelly transfered but AFNetworking fires the success block. Also the http response code received is set to 200 OK.
This situation only happens on a 3G connection. On WiFi we correctly receive all the files.
Can anyone give us any hints on what can be causing this behaviour?
Edit, 2012-05-10 I've detected that the problem may be elsewhere, what I am doing is checking the CRC of the file and compare it to the expected CRC. However (and it only happens when the connection is over 3G) the CRC check fails. Below are some snippets of the code I'm using to download the file and then check it's CRC:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlNS];
AFImageRequestOperation * imageRequestOperation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
cacheName: nil
success: ^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image)
{
[self.class postProcessDownloadAfNetworking: request andResponse: response resultImage: image error: nil];
}
failure: ^(NSURLRequest * request, NSHTTPURLResponse * response, NSError * error)
{
[self.class postProcessDownloadAfNetworking: request andResponse: response resultImage: nil error: error];
}];
imageRequestOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:obj.destinationFilename append:NO];
[imageRequestOperation start];
And then in the callback method:
if(error == nil)
{
NSData * data = [NSData dataWithContentsOfFile:imgData.destinationFilename];
uint32_t fileCrcInt = [data crc32];
NSString * fileCrcHex = [NSString stringWithFormat:@"%2X", (int) fileCrcInt] ;
NSString * fileCrcHex2 = [NSString stringWithFormat:@"000000%@", fileCrcHex] ;
fileCrcHex2 = [fileCrcHex2 substringFromIndex:[fileCrcHex2 length]-8];
// Compare CRC
if( [expectedCRC isEqualToString:fileCrcHex2] )
{
(...)
Is it possible that the instruction [NSData dataWithContentsOfFile:] is reading the file before the Output Stream from AFNetworking writes it completely? Maybe I'm encountering some kind of iOS disk cache or something like that.
In the absence of other data, I'll take a wild guess:
Certain file types may be subject to a transparent proxy over 3G, which may alter those files. This is with widely-recognized file types with lossy compression. Basically, if you're trying to download a JPEG the proxy might deliver a smaller JPEG than you expect. The cell provider considers it "close enough", and the doubly-compressed JPEG is smaller (and far uglier). Naturally, the re-compressed image will have a different CRC.
This may be true of other file types as well.
I have read reports of T-Mobile doing this. I think it's been noted with other cell providers, too.
There's two possible fixes:
As noted by Tony Million in a comment below, switching to HTTPS will fix this problem as the proxy will no longer be in the middle of the communication.
If your resource is available via HTTPS, this is a fantastic and simple fix.
If not, you can try adding a HTTP header intended to defeat this. I can't verify it will work for you, as my cell provider doesn't play this particular game:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5
The idea is to add a no-transform cache-control HTTP header to your request. This should disallow the server from making this kind of change.