5

I'm trying to send data to a server with JSON. I am able to create my NSDictionary with my objects and key parameters. But I want to send my picture, and the picture is UIImage.

 NSDictionary* mainJSON = [NSDictionary dictionaryWithObjectsAndKeys:
                          @"John",
                          @"First_Name",
                          @"McCintosh",
                          @"Last_name",
                          <HERE I WANT PICTURE>,
                          @"Profile_picture",
                          nil];

 // Here I convert to NSDATA 
 NSData * jsonData = [NSJSONSerialization dataWithJSONObject:mainJSON options:NSJSONWritingPrettyPrinted error:&error];

 // Sending operation :
 dispatch_async(kBgQueue, ^
                   {
                       NSData * data = [NSData dataWithContentsOfURL:@"addresSERVER"];
                       [self performSelectorOnMainThread:@selector(receivedResponseFromServer:)
                                              withObject:data
                                           waitUntilDone:YES];
                   }
                   );

So I'm wondering how can I add my picture in my NSDictionary? Because I want to send the content of my picture. If I add my object UIImage... I'll send the whole object right?

Thanks

bpolat
  • 3,879
  • 20
  • 26
manonthemoon
  • 2,611
  • 8
  • 26
  • 40
  • Okay interesting... When you say "see the syntax", that's mean that there is a way to send that with Json? Or I should change solution? – manonthemoon May 29 '13 at 16:03
  • Hot Licks is wrong. See Roman's answer. – Ben Coffman May 29 '13 at 16:05
  • You should not send large images (or other large data objects) as Base64 in JSON. The overhead in terms of time and space is large, and there are other better ways to send this data. – Hot Licks May 29 '13 at 17:37

4 Answers4

8

You should convert the UIImage to NSString. Use the category of NSData called NSDataAdditions.You can find here: NSDataAdditions category

How to Use:

//Convert an Image to String
UIImage *anImage;
NSString imageString = [UIImagePNGRepresentation(anImage) base64Encoding];

//To retrieve
NSData *data = [NSData dataWithBase64EncodedString:imageString];
UIImage *recoverImage = [[UIImage imageWithData:data];
  • 1
    Just so people know, NSData has it's own base64EncodedStringWithOptions: method since iOS7, no need for a category anymore. – Sebastien Peek Nov 23 '16 at 18:47
4

I wouldn't typically post an image using JSON. Although it is technically possible to encode an image into text, I don't think that's how JSON is intended to be used and I would personally avoid the practice.

Deal with images as NSData. That's what they are. There are tons of examples online that illustrate how to do this.

One common approach is to upload an image to a web server, then take the URL of the uploaded image and add that to your JSON dictionary, such that your submitted JSON dictionary carries a string representing the URL of the image to download -- not the image itself.

isaac
  • 4,867
  • 1
  • 21
  • 31
  • I would upload the image and the JSON separately as well. +1 – lnafziger May 29 '13 at 16:20
  • Thanks for sharing knowledge, now I understand that JSON supports just strings numbers and booleans. But if I encode the image is possible... What do you think about the solution of Roman ? It looks good no? For the moment I just have problem to make work base64encoding... Or maybe I should forget JSON and try the solution in the link "illustrate how to do this" – manonthemoon May 29 '13 at 16:22
  • 1
    @manonthemoon I think that Roman's answer may technically work, but it is using JSON in ways that it's not really intended to be used and there are a few ways I can see it going wrong. It's only slightly more work to do this in a way that is "better" - eg, encode the image, upload the image, then take the URL for the uploaded image, add it to your JSON dictionary, and upload the JSON dictionary. The link I included shows precisely how to encode and upload the image itself. – isaac May 29 '13 at 16:25
  • @manonthemoon this is the appropriate way to do it, you should not embed your data inside JSON. – tolgamorf May 29 '13 at 16:41
  • Okay, I'm trying the way of Isaac ;) . I have some warnings. This post exists since 2008, so I have to make code compiling. I'll give you feedback if it works, with the code compiling in current Xcode and iOS SDK versions. Thanks ;) – manonthemoon May 29 '13 at 16:46
  • Goodluck @manonthemoon -- here's another link fyi: http://stackoverflow.com/questions/12004054/upload-image-to-server-from-ios-device – isaac May 29 '13 at 16:54
  • 2
    @manonthemoon FYI, for downloading and uploading data, I personally use [AFNetworking](https://github.com/AFNetworking/AFNetworking), which is a powerful networking library for iOS/MacOSX. You should check it out as well. – tolgamorf May 29 '13 at 17:22
  • Thanks guys! I looked AFNetworking, it's true that is really powerful. I will post my finale code very soon. When it will be clean. Hopefully it will work, but there are not reason that it won't work ;) . Thanks again – manonthemoon May 29 '13 at 18:51
2

You can try send UIImage with NSString like this: Swift 3:

if let jpegData = UIImageJPEGRepresentation(image, 1.0) {
    var encodedString = jpegData.base64EncodedString()
    var mainJSON = [
        "First_Name" : "John",
        "Last_name" : "McCintosh",
        "Profile_picture" : encodedString
    ]

}

Objective-c:

NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
NSString *encodedString = [imageData base64Encoding];


 NSDictionary* mainJSON = [NSDictionary dictionaryWithObjectsAndKeys:
                          @"John",
                          @"First_Name",
                          @"McCintosh",
                          @"Last_name",
                          encodedString,
                          @"Profile_picture",
                          nil];

This is Base64 format so you can decode this in any language

Roman Barzyczak
  • 3,785
  • 1
  • 30
  • 44
  • Okay, I'm gonna try this solution :) I'll give you feedback in some minutes. Thanks – manonthemoon May 29 '13 at 16:07
  • Hey, for the UIImageJPEGRepresentation, it works without problem. But for base64encoding, he can't find the method. I have this warning : 'no visible @interface for declares the selector base64 Encoding' – manonthemoon May 29 '13 at 16:13
  • @manonthemoon I think `base64encoding` is a custom method implemented in a category for NSData. I found one with the same name [here](http://colloquy.info/project/browser/trunk/Additions/NSDataAdditions.m), maybe you can use it. – tolgamorf May 29 '13 at 16:36
  • [NSData base64Encoding] has been deprecated since iOS 7, please use [NSData base64EncodedStringWithOptions:] – Sebastien Peek Nov 23 '16 at 18:48
0

Okay, Thansk to @tolgamorf and @isaac, I tried using AFNetwork. I could do what I want. It's powerful and simple.

NSURL *url = [NSURL URLWithString:@"http://api-base-url.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"avatar.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST"  path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg"  mimeType:@"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[httpClient enqueueHTTPRequestOperation:operation];

I took the code from official documentation from here .

Enjoy

manonthemoon
  • 2,611
  • 8
  • 26
  • 40