问题
I'm using AFNetworking2 to download files from my AWS S3 bucket Everything works fine except when I set the Content-Encoding: gzip for the files. AFNetworking fails to download the partial content response coming back from the server and it gives me the following error:
Error Domain=NSURLErrorDomain Code=-1015 "cannot decode raw data" UserInfo=0x10d2d8ce0 {NSUnderlyingError=0x10d1ace80 "cannot decode raw data", NSErrorFailingURLStringKey=http://s3.amazonaws.com/awdtest/fullzip.pdf, NSErrorFailingURLKey=http://s3.amazonaws.com/awdtest/fullzip.pdf, NSLocalizedDescription=cannot decode raw data}
however, when I remove the "Content-Encoding: gzip" metadata from my file, it works fine. I know that my server supports range request and I have tested it using other methods and it worked fine.
here is the HTTP response from my server:
HTTP/1.1 200 OK
x-amz-id-2: k5b65TtAgrD5Cn3N2aixCCdi6qAmg4j9iuOSNaO0uMRKLHPTQ+DMaA20u9j1CNzA
x-amz-request-id: 7AE5A7DD81ED2B88
Date: Fri, 16 May 2014 04:45:17 GMT
Content-Encoding: gzip
Last-Modified: Fri, 16 May 2014 04:44:51 GMT
ETag: "88bbe0b318bf11dd56a31176d3384e78"
Accept-Ranges: bytes
Content-Type: application/pdf
Content-Length: 1243325
Server: AmazonS3
Here are the sample files that I'm using:
https://s3.amazonaws.com/awdtest/full.pdf
https://s3.amazonaws.com/awdtest/fullzip.pdf (gzipped and have the Content-Encoding set to gip)
I would appreciate it if someone could help me with this issue.
PS: I have already tried the followings and it still does not work
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[request setValue:@"deflate" forHTTPHeaderField:@"Accept-Encoding"];
[request setValue:@"gzip, deflate" forHTTPHeaderField:@"Accept-Encoding"];
回答1:
Use Wireshark to see the recevied http body.
It could be the responseSerializer which you used can't parse the raw data .
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
回答2:
Ok, not sure how you're going about downloading this, or what your purpose is. So, I'm assuming you're using the iOS 7 APIs, specifically an AFHTTPSessionManager, and you're after the raw data of the file. Given that, I wrote a Data serializer to use, and then the actual code is very short:
Serializer (kinda weird):
@interface FFDataResponseSerializer : AFHTTPResponseSerializer
@end
@implementation FFDataResponseSerializer
- (instancetype)init
{
self = [super init];
if (!self)
{
return nil;
}
self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/pdf", nil];
return self;
}
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error])
{
return nil;
}
return data;
}
@end
And then, in my code:
NSURLSessionConfiguration *aURLSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
aURLSessionConfiguration.HTTPAdditionalHeaders = @{@"Accept-Encoding": @"gzip, deflate",
@"Accept": @"application/pdf"};
AFHTTPSessionManager *urlManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:aURLSessionConfiguration];
urlManager.responseSerializer = [FFDataResponseSerializer serializer];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://s3.amazonaws.com/awdtest/fullzip.pdf"]];
NSURLSessionDataTask *dataTask = [urlManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error)
{
NSLog(@"error: %@", error);
}
else
{
NSLog(@"response: %@, responseObject: %@", response, responseObject);
// responseObject is your NSData Object with the PDF data inside of it.
}
}];
[dataTask resume];
You'll obviously want to handle errors, keep ahold of the variables you'll want to reuse, etc, etc...
来源:https://stackoverflow.com/questions/23692906/afnetworking-fails-to-resume-downloads-when-content-encoding-gzip-is-set