如何通过填充NSDictionary以JSON格式发送UIImage

5

我正在尝试使用JSON将数据发送到服务器。 我能够创建带有对象和关键参数的NSDictionary。 但是我想发送我的图片,而这张图片是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];
                   }
                   );

我在想如何将我的照片添加到NSDictionary中?因为我想发送照片的内容。如果我添加UIImage对象...那么我会发送整个对象,对吗?

谢谢


好的,有趣... 当你说“看语法”时,那就意味着有一种方法可以使用Json发送吗?还是我应该改变解决方案? - manonthemoon
Hot Licks 是错误的。请参考 Roman 的回答。 - Ben Coffman
不应该将大型图像(或其他大型数据对象)作为Base64发送到JSON中。从时间和空间的角度来看,开销很大,并且有其他更好的方法来发送这些数据。 - Hot Licks
4个回答

8

您应该将UIImage转换为NSString。使用NSData的类别称为NSDataAdditions。您可以在此处找到: NSDataAdditions类别

如何使用:

//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
提醒大家知道,自从iOS7以来,NSData已经有了自己的base64EncodedStringWithOptions:方法,不再需要使用category了。 - Sebastien Peek

4

我通常不会使用JSON发布图片。虽然技术上可以将图像编码为文本,但我认为这不是JSON的预期使用方式,个人会避免这种做法。

将图像处理为NSData。这就是它们的本质。有很多在线示例说明如何执行此操作

一种常见方法是将图像上传到Web服务器,然后获取已上传图像的URL,并将URL添加到您的JSON字典中,以便您提交的JSON字典携带表示要下载的图像的URL字符串,而不是图像本身。


我也会分别上传图像和JSON。 +1 - lnafziger
感谢分享知识,现在我明白JSON只支持字符串、数字和布尔类型。但如果我编码图像是可能的... 你对Roman的解决方案有什么看法?看起来不错,对吧? 目前我只有一个问题,就是如何使base64编码工作... 或者我应该忘记JSON,尝试链接中的解决方案“说明如何做到这一点”? - manonthemoon
1
@manonthemoon 我认为Roman的答案在技术上可能是可行的,但它使用了JSON的方式并不是真正意图使用的方式,而且我可以看到有几种可能出错的情况。用一种更好的方式来完成这个任务只需要稍微多做一点工作 - 例如,编码图像,上传图像,然后获取上传图像的URL,将其添加到您的JSON字典中,并上传JSON字典。我包含的链接精确地展示了如何对图像本身进行编码和上传。 - isaac
2
@manonthemoon,关于下载和上传数据,我个人使用AFNetworking,它是一款适用于iOS/MacOSX的强大网络库。你也应该去看看。 - tolgamorf
谢谢大家! 我看了一下AFNetworking,确实非常强大。 我很快就会发布我的最终代码。 等它变得更加简洁时,希望它能够正常工作,但没有理由它不会 ;)。再次感谢。 - manonthemoon
显示剩余3条评论

2
您可以像这样使用NSString发送UIImage: 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];

这是Base64格式,因此您可以在任何语言中解码它。

好的,我会尝试这个解决方案 :) 我会在几分钟内给你反馈。谢谢 - manonthemoon
嘿,对于UIImageJPEGRepresentation,它可以正常工作。 但是对于base64编码,他找不到方法。我收到了这个警告:“没有可见的@interface声明选择器base64编码”。 - manonthemoon
@manonthemoon 我认为base64encoding是在NSData的类别中实现的自定义方法。我找到了一个同名的网址,也许你可以使用它。 - tolgamorf
自iOS 7起,[NSData base64Encoding]已被弃用,请使用[NSData base64EncodedStringWithOptions:]。 - Sebastien Peek

0

好的,感谢 @tolgamorf 和 @isaac,我尝试使用 AFNetwork。 我能够做到我想要的。它强大且简单。

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];

我从这里的官方文档中获取了代码。

祝使用愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接