做一个App需要上传图片。没想使用一些比较出名的开源库,毕竟可以练练手。这里是ASI和AF的Github连接,有兴趣的读者可以去看看这些出色的开源库。这里还给出一篇优快云上面的关于这些开源库的表格对比的 博客文章。
之前在StackOverFlow上面搜过一些关于IOS 上传文件的讨论,下面的代码是参考了上面一个讨论的,读者可以看看这上面的话题讨论。
我没有封装一个更好的类来提供完善的接口来完成上传文件的操作,而是直接写Http协议。读者完全可以写一个例如”HttpMultiPartFormatter”之类的类来完成这些工作。下面是代码片段,在我的iphone上跑起来挺好的。
#define MEDIA_CONTENT_TYPE @"multipart/form-data" #define BOUNDARY_CONSTANT @"AnyNameYouLike" @interface UploadViolationTask () <HttpUploadProgressDelegate , HttpDelegate> @property (nonatomic , strong) HttpOperation *currentOperation; @end @implementation UploadViolationTask - (void)uploadSessionWithPlace:(NSString*)place reason:(NSString*)reason carNumber:(NSString*)carNumber image:(UIImage*)image andImageFileName:(NSString*)fileName { HttpOperation *operation = [[HttpOperation alloc] init]; self.currentOperation = operation; [operation setUrl:URL_SendViolationSession]; [operation setTimeOut:30]; [operation setOperationDescription:@"SaveViolationSession"]; [operation setContentType:MEDIA_CONTENT_TYPE withBoundary:BOUNDARY_CONSTANT]; [operation setMethod:@"POST"]; [operation setCachePolicy:NSURLRequestReloadIgnoringCacheData]; [operation setHTTPShuoldHandleCookes:NO]; [operation setUploadProgressDelegate:self]; [operation setCommonDelegate:self]; NSString *userID = [[PersonalInfoRecorder sharedInstance] userID]; NSString *schoolID = [[PersonalInfoRecorder sharedInstance] schoolID]; NSMutableData *body = [[NSMutableData alloc] init]; NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:place , @"illegal.place" , reason , @"illegal.type.id" , carNumber , @"illegal.vehPlate" , userID , @"illegal.creation.id" , schoolID , @"illegal.schoolInfo", fileName , @"fileFileName" , nil]; /* Add the attach params at first */ for(NSString* param in [params allKeys]) { [body appendData:[[NSString stringWithFormat:@"--%@\r\n" , BOUNDARY_CONSTANT] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n" , param] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params valueForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]]; } /* Add the image content */ [body appendData:[[NSString stringWithFormat:@"--%@\r\n" , BOUNDARY_CONSTANT] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n" , fileName] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n" dataUsingEncoding:NSUTF8StringEncoding] ]; [body appendData:[@"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData: UIImageJPEGRepresentation(image, 0.1)]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n" , BOUNDARY_CONSTANT] dataUsingEncoding:NSUTF8StringEncoding]]; [operation setPostLength:[body length]]; [operation setBody:body]; [operation submit]; }
里面的一些常量大家自己定义就好了。里面的图片的Content-Type: application/octet-streams 是要告诉服务器这是个任意的二进制文件。因为以后封装起来,还可以用来读其他的文件类型,所以就随便用了这个。当然你要准确的话,你可以写成image/jpeg 或者 image/png这样来表示这是一个文件文件。
----------------------------------------------------------
顺带一提的是关于IOS里面 NSURLConnection的上传进度的问题。这个其实很简单,在NSURLConnectionDelegate里面有一个方法可以知道本次上传数据量,当前上传数据总量和总共要上传数据量的。也顺便贴一下代码吧。
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
/* bytesWritten How many bytes were sent to server at this time */
/* totalBytesWritten The number of bytes that were sent to the server currently */
/* totalBytesExpectedToWrite The number of bytes that we want to send to the server */
CGFloat progress = totalBytesWritten / (CGFloat)totalBytesExpectedToWrite;
if([self.uploadProgressDelegate respondsToSelector:@selector(httpOperation:updatedToNewProgress:)])
{
[self.uploadProgressDelegate httpOperation:self updatedToNewProgress:progress];
}
}
在那个delegate里面你就可以用progress来刷新你的进度条啦。
就这么多吧。不知道打错了多少字。下班咧。