Ios 使用Base64和JSON上传大型图像
我正在使用此函数使用Ios 使用Base64和JSON上传大型图像,ios,objective-c,json,base64,nsurlconnection,Ios,Objective C,Json,Base64,Nsurlconnection,我正在使用此函数使用JSON将图像上载到服务器。为此,我首先将图像转换为NSData,然后使用Base64转换为NSString。当图像不是很大时,该方法可以很好地工作,但是当我尝试上载2Mb图像时,它崩溃了 问题是,即使调用了didReceiveResponse方法以及返回(null)的didReceiveData,服务器也不会接收到我的映像。起初我认为这是一个超时问题,但即使将其设置为1000.0,它仍然不起作用。有什么想法吗?谢谢你的时间 以下是我当前的代码: - (void) imag
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]);
}
请不要认为这是最后的选择,这只是我的观察 我认为你应该把数据分块发送,而不是完整的数据。 我在YouTube视频上传案例中看到过这样的方法。他们发送大量NSData(视频文件的NSData),并将大量NSData分块发送 他们使用相同的方法上传大数据 所以谷歌应该对Youtube数据上传API做些什么。你应该搜索Youtube上传者使用的方法
我希望它能对您有所帮助。我最终决定上传Base64图像,将其拆分为更小的子字符串。为了做到这一点,并且由于我需要许多
NSURLConnections
,我创建了一个名为TagConnection
的子类,它为每个连接提供一个标记,以便它们之间不会出现混淆
然后我在MyViewController
中创建了一个TagConnection
属性,以便从任何函数访问它。如您所见,有一个-startSyncLoad:withTag:
函数,用于分配和初始化TagConnection
和-connection:didReceiveData:
函数,当我收到服务器的响应时,该函数会将其删除
参考-uploadImage
函数,它首先将图像转换为字符串,然后将其拆分,并将块放入JSON请求中。它一直被调用,直到变量偏移量大于字符串长度,这意味着所有块都已上载
您还可以通过每次检查服务器响应并在返回成功时仅调用-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
#import "TagConnection.h"
@interface MyViewController : UIViewController
@property (strong, nonatomic) TagConnection *conn;
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
@interface TagConnection : NSURLConnection {
NSString *tag;
}
@property (strong, nonatomic) NSString *tag;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag;
@end
#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, 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];
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,@"design_id",[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
您是否在php网页上添加了日志,以查看是否至少调用了url?就像文件日志或sql日志一样?实际上,服务器端程序员告诉我,如果网站收到任何数据,总是会返回响应。因此,我的结论是,他甚至没有收到请求代码>您收到的响应是什么?如果你真的想知道电线上发生了什么,那就找一个类似嗅探器的(免费试用)。我一直在使用它,甚至SSL也在使用。在这里查看我的答案,它将帮助您。类似的事情?:你能帮我查一下服务器端代码吗?我无法在php方面做到这一点!对不起,这不是我的事。