我正在使用此功能使用
JSON将图像上传到服务器.为此,我首先将图像转换为NSData,然后使用Base64转换为NSString.当图像不是很大时,该方法可以正常工作,但是当我尝试上传2Mb图像时,它会崩溃.
问题是,即使调用didReceiveResponse方法以及返回(null)的didReceiveData,服务器也不会接收我的图像.起初我认为这是一个超时问题,但即使将其设置为1000.0它仍然不起作用.任何的想法?谢谢你的时间!
这是我目前的代码:
- (void) imageRequest { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.myurltouploadimage.com/services/v1/upload.json"]]; NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0]; NSString *path = [NSString stringWithFormat:@"%@/design%i.png",docDir,designNum]; NSLog(@"%@",path); NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]); [Base64 initialize]; NSString *imageString = [Base64 encode:imageData]; NSArray *keys = [NSArray arrayWithObjects:@"design",nil]; NSArray *objects = [NSArray arrayWithObjects:imageString,nil]; NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error]; [request setHTTPMethod:@"POST"]; [request setValue:[NSString stringWithFormat:@"%d",[jsonData length]] forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; [[NSURLConnection alloc] initWithRequest:request delegate:self]; NSLog(@"Image uploaded"); } - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"didReceiveResponse"); } - (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); }
解决方法
我最终决定将Base64图像上传到较小的子串中.为了做到这一点,并且因为我需要许多NSURLConnections,我创建了一个名为TagConnection的子类,它为每个连接提供一个标记,这样它们之间就不会产生混淆.
然后我在MyViewController中创建了一个TagConnection属性,目的是从任何函数访问它.正如您所看到的,有-startAsyncLoad:withTag:分配和插入TagConnection的函数和-connection:didReceiveData:当我从服务器收到响应时删除它的那个.
参考-uploadImage函数,首先,它将图像转换为字符串,然后将其拆分并将块放在JSON请求中.它被调用,直到变量offset大于字符串长度,这意味着已经上传了所有块.
您还可以通过每次检查服务器响应并仅在返回成功时调用-uploadImage函数来证明每个块已成功上载.
我希望这是一个有用的答案.谢谢.
TagConnection.h
@interface TagConnection : NSURLConnection { NSString *tag; } @property (strong,nonatomic) NSString *tag; - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag; @end
TagConnection.m
#import "TagConnection.h" @implementation TagConnection @synthesize tag; - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag { self = [super initWithRequest:request delegate:delegate startImmediately:startImmediately]; if (self) { self.tag = tag; } return self; } - (void)dealloc { [tag release]; [super dealloc]; } @end
MyViewController.h
#import "TagConnection.h" @interface MyViewController : UIViewController @property (strong,nonatomic) TagConnection *conn;
MyViewController.m
#import "MyViewController.h" @interface MyViewController () @end @synthesize conn; bool stopSending = NO; int chunkNum = 1; int offset = 0; - (IBAction) uploadImageButton:(id)sender { [self uploadImage]; } - (void) startAsyncLoad:(NSMutableURLRequest *)request withTag:(NSString *)tag { self.conn = [[[TagConnection alloc] initWithRequest:request delegate:self startImmediately:YES tag:tag] autorelease]; } - (void) uploadImage { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.mywebpage.com/upload.json"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1000.0]; NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,YES) objectAtIndex:0]; NSString *path = [NSString stringWithFormat:@"%@/design%i.png",designNum]; NSLog(@"%@",path); NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]); [Base64 initialize]; NSString *imageString = [Base64 encode:imageData]; NSUInteger length = [imageString length]; NSUInteger chunkSize = 1000; NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset; NSString *chunk = [imageString substringWithRange:NSMakeRange(offset,thisChunkSize)]; offset += thisChunkSize; NSArray *keys = [NSArray arrayWithObjects:@"design",@"design_id",@"fragment_id",nil]; NSArray *objects = [NSArray arrayWithObjects:chunk,[NSString stringWithFormat:@"%i",chunkNum],nil]; NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error]; [request setHTTPMethod:@"POST"]; [request setValue:[NSString stringWithFormat:@"%d",[jsonData length]] forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; [self startAsyncLoad:request withTag:[NSString stringWithFormat:@"tag%i",chunkNum]]; if (offset > length) { stopSending = YES; } } - (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSError *error; NSArray *responseData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; if (!responseData) { NSLog(@"Error parsing JSON: %@",error); } else { if (stopSending == NO) { chunkNum++; [self.conn cancel]; self.conn = nil; [self uploadImage]; } else { NSLog(@"---------Image sent---------"); } } } @end