IOS NSURlSession 后台上传文件小结(可以上传多张图片)

由于项目还在开发阶段,只能贴上部分代码,敬请谅解;

注意点:

在后台上传必须是调用此方法:uploadTaskWithRequest:  fromFile:其他方法尝试均会报错;具体原因请查看:http://quabr.com/38349943/background-upload-using-uploadtaskwithrequest-with-nsdata 

代码部分:

#import "AppDelegate.h"

#import "ViewController.h"

#import "define.h"

#define IS_IOS10ORLATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10)

#define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx"

#define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]

typedef void(^CompletionHandlerType)();@interface AppDelegate ()@property (strong, nonatomic) NSMutableDictionary *completionHandlerDictionary;

//@property (strong, nonatomic) NSURLSessionUploadTask *uploadTask;

@property (strong, nonatomic) NSURLSession *backgroundSession;

@property (strong, nonatomic) NSData *resumeData;

@property (strong, nonatomic) UILocalNotification *localNotification;

@property (nonatomic, strong) NSMutableArray *mutableArr;

@property (nonatomic, strong) NSMutableArray *dataMutableArr;

//用于判断最后一个任务完成上传 才发出通知

@property (nonatomic) NSInteger dataNum;

@end

@implementation AppDelegate

- (NSMutableArray *)mutableArr{

if (!_mutableArr) {

_mutableArr = [NSMutableArray array];

}

return _mutableArr;

}

- (NSMutableArray *)dataMutableArr{

if (!_dataMutableArr) {

_dataMutableArr = [NSMutableArray array];

}

return _dataMutableArr;

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

self.dataNum = 0;

self.backgroundSession = [self backgroundURLSession];

[self initLocalNotification];

// ios8后,需要添加这个注册,才能得到授权

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {

UIUserNotificationType type =  UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type

categories:nil];

[[UIApplication sharedApplication] registerUserNotificationSettings:settings];

// 通知重复提示的单位,可以是天、周、月

self.localNotification.repeatInterval = 0;

} else {

// 通知重复提示的单位,可以是天、周、月

self.localNotification.repeatInterval = 0;

}

UILocalNotification *localNotification = [launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];

if (localNotification) {

[self application:application didReceiveLocalNotification:localNotification];

}

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];

self.window.rootViewController = nvc;

[self.window makeKeyAndVisible];

return YES;

}

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {

// 你必须重新建立一个后台 seesion 的参照

// 否则 NSURLSessionDownloadDelegate 和 NSURLSessionDelegate 方法会因为

// 没有 对 session 的 delegate 设定而不会被调用。参见上面的 backgroundURLSession

NSURLSession *backgroundSession = [self backgroundURLSession];

NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession);

// 保存 completion handler 以在处理 session 事件后更新 UI

[self addCompletionHandler:completionHandler forSession:identifier];

}

#pragma mark Save completionHandler

- (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier {

if ([self.completionHandlerDictionary objectForKey:identifier]) {

NSLog(@"Error: Got multiple handlers for a single session identifier.  This should not happen.\n");

}

[self.completionHandlerDictionary setObject:handler forKey:identifier];

}

- (void)callCompletionHandlerForSession:(NSString *)identifier {

CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey: identifier];

if (handler) {

[self.completionHandlerDictionary removeObjectForKey: identifier];

NSLog(@"Calling completion handler for session %@", identifier);

handler();

}

}

#pragma mark - Local Notification

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

[[UIApplication sharedApplication] cancelAllLocalNotifications];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"上传通知"

message:notification.alertBody

delegate:nil

cancelButtonTitle:@"确定"

otherButtonTitles:nil];

[alert show];

// 图标上的数字减1

application.applicationIconBadgeNumber -= 1;

}

- (void)applicationWillResignActive:(UIApplication *)application {

// 图标上的数字减1

application.applicationIconBadgeNumber -= 1;

}

- (void)initLocalNotification {

self.localNotification = [[UILocalNotification alloc] init];

self.localNotification.fireDate = [[NSDate date] dateByAddingTimeInterval:5];

self.localNotification.alertAction = nil;

self.localNotification.soundName = UILocalNotificationDefaultSoundName;

self.localNotification.alertBody = @"上传完成了!";

self.localNotification.applicationIconBadgeNumber = 1;

self.localNotification.repeatInterval = 0;

}

- (void)sendLocalNotification {

[[UIApplication sharedApplication] scheduleLocalNotification:self.localNotification];

}

#pragma mark - backgroundURLSession

- (NSURLSession *)backgroundURLSession {

static NSURLSession *session = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

NSString *identifier = @"from.hx";

NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];

session = [NSURLSession sessionWithConfiguration:sessionConfig

delegate:self

delegateQueue:[NSOperationQueue mainQueue]];

});

return session;

}

- (void)uploadDataWithImageFileArr:(NSMutableArray *)array andIp:(NSString *)ip{

NSURL *uploadURL = [NSURL URLWithString:ip];

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:uploadURL];

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];

[request addValue:@"text/html" forHTTPHeaderField:@"Accept"];

[request setHTTPMethod:@"PUT"];

[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];

[request setTimeoutInterval:60];

for (int i = 0; i < array.count; i++) {

NSDate *nowdate = [NSDate date];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

[formatter setDateStyle:NSDateFormatterMediumStyle];

[formatter setDateFormat:@"MMddHHmm"];

NSString *datestr = [formatter stringFromDate:nowdate];

NSString *identifier = @"from.hx";

NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];

NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig

delegate:self

delegateQueue:[NSOperationQueue mainQueue]];

NSURLSessionUploadTask *task        = [session uploadTaskWithRequest:request fromFile:[NSURL URLWithString:array[i]]];

[task resume];

}

}

- (void)uploadDataWithImageArr:(NSMutableArray *)array andIp:(NSString *)ip{

_dataMutableArr = array;

NSURL *uploadURL = [NSURL URLWithString:ip];

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:uploadURL cachePolicy:0 timeoutInterval:60];

// 1> PUT方法

// PUT

//    1) 文件大小无限制

//    2) 可以覆盖文件

// POST

//    1) 通常有限制2M

//    2) 新建文件,不能重名

[request setHTTPMethod:@"POST"];

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];

[request addValue:@"text/html" forHTTPHeaderField:@"Accept"];

for (int i = 0; i < array.count; i++) {

NSDate *nowdate = [NSDate date];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

[formatter setDateStyle:NSDateFormatterMediumStyle];

[formatter setDateFormat:@"MMddHHmmss"];

NSString *datestr = [formatter stringFromDate:nowdate];

ZRLog(@"datestr:%@", datestr);

NSString *identifier = @"from.hx";

NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];

NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig

delegate:self

delegateQueue:[NSOperationQueue mainQueue]];

NSURLSessionUploadTask *task        = [session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:[self saveImage:array[i] WithName:[NSString stringWithFormat:@"%@.jpeg",datestr]]]];

[task resume];

}

}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{

NSString * htmlString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

ZRLog(@"htmlstring:+++++++:%@", htmlString);

NSError *error = nil;

id jsonObject = [NSJSONSerialization

JSONObjectWithData:data options:NSJSONReadingAllowFragments

error:&error];

if (jsonObject != nil && error == nil){

ZRLog(@"Successfully deserialized...");

//如果jsonObject是字典类

if ([jsonObject isKindOfClass:[NSDictionary class]]){

NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;

NSLog(@"Dersialized JSON Dictionary = %@", deserializedDictionary);

}

//如果jsonObject是数组类

else if ([jsonObject isKindOfClass:[NSArray class]]){

NSArray *deserializedArray = (NSArray *)jsonObject;

ZRLog(@"Dersialized JSON Array = %@", deserializedArray);

[self.mutableArr addObjectsFromArray:deserializedArray];

ZRLog(@"++++++++++dataMutableArr:%@", self.mutableArr);

//  ZRLog(@"uuid:%@", deserializedArray[0][@"uuid"]);

} else {

NSLog(@"I can't deal with it");

}

}

else if (error != nil){

NSLog(@"An error happened while deserializing the JSON data.");

}else if ([data length] == 0 &&error == nil){

NSLog(@"No data was returned after serialization.");

}

else if (error != nil){

NSLog(@"An error happened = %@", error);

}

}

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{

if (session.configuration.identifier) {

// 调用在 -application:handleEventsForBackgroundURLSession: 中保存的 handler

[self callCompletionHandlerForSession:session.configuration.identifier];

}

}

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{

if (error) {

// check if resume data are available

if ([error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]) {

NSData *resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];

//通过之前保存的resumeData,获取断点的NSURLSessionTask,调用resume恢复下载

self.resumeData = resumeData;

}

} else {

_dataNum++;

if (_dataNum == _dataMutableArr.count) {

[self sendLocalNotification];

[self postDownlaodProgressNotification:@"1"];

}

}

}

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{

//self.progressview.progress = totalBytesSent/(float)totalBytesExpectedToSend;

NSString *strProgress = [NSString stringWithFormat:@"%.2f",totalBytesSent/(float)totalBytesExpectedToSend];

[self postDownlaodProgressNotification:strProgress];

ZRLog(@"------------already sent:%lld",bytesSent);

ZRLog(@"------------totoal to send:%lld",totalBytesSent);

ZRLog(@"------------expected send:%lld",totalBytesExpectedToSend);

}

- (void)postDownlaodProgressNotification:(NSString *)strProgress {

NSDictionary *userInfo = @{@"progress":strProgress};

dispatch_async(dispatch_get_main_queue(), ^{

[[NSNotificationCenter defaultCenter] postNotificationName:kuploadProgressNotification object:nil userInfo:userInfo];

});

}

/**

* 保存图片

*/

-(NSString *)saveImage:(UIImage *)tempImage WithName:(NSString *)imageName{

NSData* imageData;

//    //判断图片是不是png格式的文件

//    if (UIImagePNGRepresentation(tempImage)) {

//        //返回为png图像。

//        imageData = UIImagePNGRepresentation(tempImage);

//    }else {

//        //返回为JPEG图像。

//        imageData = UIImageJPEGRepresentation(tempImage, 1.0);

//    }

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

NSString* documentsDirectory = [paths objectAtIndex:0];

NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:imageName];

NSArray *nameAry=[fullPathToFile componentsSeparatedByString:@"/"];

ZRLog(@"===imageName========%@", imageName);

ZRLog(@"===fullPathToFile===%@",fullPathToFile);

ZRLog(@"===FileName===%@",[nameAry objectAtIndex:[nameAry count]-1]);

[[self gotDataImage:tempImage fileName:imageName] writeToFile:fullPathToFile atomically:NO];

return fullPathToFile;

}

- (NSData *)gotDataImage:(UIImage *)image fileName:(NSString *)filename{

NSMutableData *fileData = [NSMutableData data];

//5.1 文件参数

/*

--分隔符

Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png"

Content-Type: image/png(MIMEType:大类型/小类型)

空行

文件参数

*/

[fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

//name:file 服务器规定的参数

//filename:Snip20160225_341.png 文件保存到服务器上面的名称

//Content-Type:文件的类型

NSDate *nowdate = [NSDate date];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

[formatter setDateStyle:NSDateFormatterMediumStyle];

[formatter setDateFormat:@"MMddHHmm"];

NSString *datestr = [formatter stringFromDate:nowdate];

[fileData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=tianmen %@; filename=%@", datestr, filename] dataUsingEncoding:NSUTF8StringEncoding]];

//[fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Sss.png\"" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:[@"Content-Type: image/jpeg" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:KNewLine];

//UIImage --->NSData

NSData *imageData = UIImageJPEGRepresentation(image,0.5);

[fileData appendData:imageData];

[fileData appendData:KNewLine];

[fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];

return fileData;

}

@end

你可能感兴趣的:(IOS NSURlSession 后台上传文件小结(可以上传多张图片))