1

I am trying to send a UIImage take with the UIImagePickerController to a server POST along with other pertinent values. But I get at the line that tries to set the dictionary value @"image" to UIImageJPEGRepresentation(image, 1.0):

-(void)sendImageToServer:(UIImage *)image
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 4;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:nil delegateQueue:queue];
    NSURL *uploadURL = [NSURL URLWithString:@"http://...."];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:uploadURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];

    [request addValue:@"application/json" forHTTPHeaderField:@"Accept"];

    [request setHTTPMethod:@"POST"];

    NSData *postData = [[NSData alloc] init];
    [postData setValue:UIImageJPEGRepresentation(image, 1.0) forKey:@"image"];
    [postData setValue:@"1" forKey:@"categories[0]"];
    [postData setValue:@"4" forKey:@"categories[1]"];

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
                                                               fromData:postData
                                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        if (!error) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            if (httpResponse.statusCode == 200) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSError *err;
                    NSDictionary *JSONDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&err];
                    NSLog(@"HTTP 200 response: %@", JSONDict);
                });
            } else {    
                NSLog(@"HTTP %ld status!", (long)httpResponse.statusCode);
            }   
        } else {
            NSLog(@"HTTP post image error: %@", error);
        }
    }];
    [uploadTask resume];
}

JSON serialization does not work here, because images are not valid JSON values. If on the other hand I try:

...
NSMutableData *postData = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:postData];

    [archiver encodeObject:UIImageJPEGRepresentation(image, 1.0) forKey:@"image"];
    [archiver encodeObject:@"1" forKey:@"categories[0]"];
    [archiver encodeObject:@"4" forKey:@"categories[1]"];
    [archiver finishEncoding];



    //NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDict options:NSJSONWritingPrettyPrinted error:&jsonError];
    //Now you can post the json data

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
                                                               fromData:postData
                                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {...

The key:value pairs archived do not seem to get to the server as such. This must be a routinely iOS coding task.

Even if I just try:

NSError *jsonError;
    NSData *postData = [NSJSONSerialization dataWithJSONObject:@{@"image":@"123",@"categories[0]":@"1",@"categories[1]":@"4"} options:NSJSONWritingPrettyPrinted error:&jsonError];

The server does not get any keys at all...

izk
  • 1,189
  • 2
  • 8
  • 23

3 Answers3

0

That's not the proper usage of NSData. It's crashing right now because NSData does not have key named image (..or the other two after that). What you need to do is create an NSDictionary and then convert that to NSData.

Do something like this instead:

NSDictionary *dictionary = [NSDictionary alloc]initWithObjectsAndKeys:image,@"image",@(1),@"categories[0]",@(4),@"categories[1]", nil];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary]; //Not currently using NSJSONSerialization since you want to post a Dictionary with an invalid NSJSONSerialization type in it.
//Now you can post the json data
Tommy Devoy
  • 13,441
  • 3
  • 48
  • 75
  • Thanks @tdevoy. I had already tried something similar, but it throws and exception in the same spot: [NSJSONSerialization datataWithJSONObject....]; I assumed a JPEG representation is not a valid JSON value: NSDictionary *dataDict = @{@"image": UIImageJPEGRepresentation(image, 1.0), @"categories[0]": @"1", @"categories[1]": @"4"}; NSError *jsonError = nil; NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDict options:NSJSONWritingPrettyPrinted error:&jsonError]; – izk Sep 23 '14 at 17:24
  • Yeah, whoops forgot that NSJSONSerialization methods only work with NSString, NSNull, NSNumber, NSArray, and NSDictionary objects. You could use NSKeyedArchiver to convert to NSData instead. – Tommy Devoy Sep 23 '14 at 17:59
0

Give a try with AFNetworking, it have a great way to make uploads, you can find the samples here: https://github.com/AFNetworking/AFNetworking#creating-an-upload-task

I personally recommend everyone to use it, since I started to use I didn't have any trouble to communicate my apps with webservers.

0

Use AFNetworking and the multi-part form post. Here is a rough example (note I am passing in a block so your implementation will vary):

AFHTTPRequestOperation *operation = [self POST:FullURLString parameters:Params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData:fileData name:fileName fileName:fileName mimeType:mimeType];
    } success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSData *responseData = [operation responseData];
        id retObj;
        NSError *error = nil;
        if (responseData) {
            retObj = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
        }
        // Pass back the serialized object (either an NSArray of type NSDictionaries or an NSArray of type customClass)
        block(retObj);

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Failed with error = [Error]: %@", error);
        block(nil);
}];
LJ Wilson
  • 14,445
  • 5
  • 38
  • 62