美文网首页
NSURLSession 后台上传文件

NSURLSession 后台上传文件

作者: d4d5907268a9 | 来源:发表于2023-12-10 15:53 被阅读0次
    #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
    

    相关文章

      网友评论

          本文标题:NSURLSession 后台上传文件

          本文链接:https://www.haomeiwen.com/subject/jdkpgdtx.html