AFNetworking 2.2.1 loading an image from Amazon S3 server
Asked Answered
M

3

9

I'm running into a problem trying to download an image on an Amazon S3 server.

I get the following error:

Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: binary/octet-stream" 

Anyone has an idea?

Mischance answered 23/3, 2014 at 0:38 Comment(2)
possible duplicate of AFNewtorking loading images from Amazon S3Zingg
That question for a much older version of AFNetworking. I'm not sure how to fix it for the 2.2.1 version.Mischance
E
16

This error is generated by

- (BOOL)validateResponse:(NSHTTPURLResponse *)response
                    data:(NSData *)data
                   error:(NSError * __autoreleasing *)error

method of AFHTTPResponseSerializer in case of unexpectable MIME type of response.

You can fix it by adding required MIME type to response serializer

// In this sample self is inherited from AFHTTPSessionManager
self.responseSerializer = [AFImageResponseSerializer serializer];
NSSet *set = self.responseSerializer.acceptableContentTypes;
self.responseSerializer.acceptableContentTypes = [set setByAddingObject:@"binary/octet-stream"];

Or you can modify AFImageResponseSerializer :

- (instancetype)init {
    self = [super init];
    if (!self) {
        return nil;
    }

    self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", @"binary/octet-stream", nil];

#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
    self.imageScale = [[UIScreen mainScreen] scale];
    self.automaticallyInflatesResponseImage = YES;
#endif

    return self;
}

But root of the problem is probably that you save your images to Amazon with wrong MIME type or without type at all. In my code I save images to Amazon with following code

S3PutObjectRequest *putObjectRequest = [ [ S3PutObjectRequest alloc ] initWithKey:keyImage    inBucket:self.s3BucketName ];
putObjectRequest.contentType = @"image/jpeg";
putObjectRequest.data = UIImageJPEGRepresentation( [ image fixOrientation ], 0.5f );
putObjectRequest.cannedACL = [ S3CannedACL publicRead ];
Euhemerism answered 23/3, 2014 at 0:53 Comment(6)
Ok thank by adding @"binary/octet-stream" to the list it work. But I agree with you the image MIME type should be set properly. Thanks a bunch.Mischance
This is broadly correct, but you should just modify the acceptableContentTypes property on an existing image response serializer, not modify the AFNetworking source.Wasp
Good idea! I have always thought that it is a readonly property. But now I see that at least in the latest AFNetworking version it is writable. Thanks!Euhemerism
I have added solution via acceptableContentTypes property.Euhemerism
thanks in my case i had add @"image/jpeg" to work fine.Odie
if you're using a regular NSURLRequest, just add [request addValue:@"image/jpeg" forHttpHeaderField:@"Content-type"];Agretha
H
0

Updated for Boto 3

You can check what MIME type it is through your S3 web interface. First select the file you are having problems with, then select the Properties view. In this view open the Metadata section.

enter image description here

If your Content-Type is binary/octet-stream it is unset. Setting it in Boto 3, is different than the above answer for Boto 2. Here is how I do it:

filename = "/home/me/image42.jpeg"     #the file I want to upload
bucketname = "myNewBucket"             #name of my S3 bucket
key = "myImages/image42.jpeg"          #desired name in S3 bucket
s3.Object(bucketname, key).put(Body=open(filename, 'rb'), ACL='public-read',ContentType='image/jpeg')
Hauteloire answered 10/1, 2016 at 16:15 Comment(0)
P
0

AFNetworking 3.1.0

You should just modify the acceptableContentTypes property on an existing image response serializer. You can use AFHTTPSessionManager do it.

NSURL *url = [NSURL URLWithString:@"http://..."];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
AFHTTPResponseSerializer *serializer = [AFHTTPResponseSerializer serializer];
serializer.acceptableContentTypes = [NSSet setWithObject:@"binary/octet-stream"];
manager.responseSerializer = serializer;

Then you can use manager to get the content of URL:

[manager GET:[url absoluteString] parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    // ...
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    // ...
}];

or use setImageWithURLRequest:placeholderImage:success:^failure:^ for get image:

UIImageView *imageView = [UIImageView new];
[[UIImageView sharedImageDownloader] setSessionManager:manager];    
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://..."]];
[imageView setImageWithURLRequest:urlRequest placeholderImage:[UIImage new] success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {
    // but image can be NSData instead of UIImage
} failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
    // ...
}];

But the response can be NSData instead of UIImage.

I hope that it helps you.

Proustite answered 8/9, 2016 at 17:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.