http://www.appcoda.com/background-transfer-service-ios7/

http://www.raywenderlich.com/51127/nsurlsession-tutorial

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html

http://blog.csdn.net/kyfxbl/article/details/18629227

http://hayageek.com/ios-nsurlsession-example/

一个很好的IOS学习网站:

http://www.appcoda.com

遇到NSURLSession后台上传文件的问题,得到这个地方的指点:

http://eyeplum.me/2014/02/26/multipart-form-data-background-nsurlsession/ 后解决,非常感谢

具体的实现:

AppDelegate.m中,加入后台处理函数

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

    self.backgroundTransferCompletionHandler = completionHandler;

}

ViewController.h加入delegate

@interface ViewController : UIViewController <UITableViewDelegate , UITableViewDataSource , NSURLSessionDelegate>

下面是具体的实现,这里任务需要,我们是串行地上传,其实并行上传更方便

//
// ViewController.m
// BackgroundTransfer
//
// Created by feixiang on 16/6/14.
// Copyright (c) 2014 ___FULLUSERNAME___. All rights reserved.
// #import "ViewController.h"
#import "FileUploadInfo.h"
#import "AppDelegate.h" // Define some constants regarding the tag values of the prototype cell's subviews.
#define CellLabelTagValue 10
#define CellStartPauseButtonTagValue 20
#define CellStopButtonTagValue 30
#define CellProgressBarTagValue 40
#define CellLabelReadyTagValue 50 @interface ViewController () @property (nonatomic, strong) NSURLSession *session;
@property (nonatomic, strong) NSURLSessionUploadTask *task;
@property (nonatomic) BOOL isDoing; @property (nonatomic, strong) NSMutableArray *arrUploadList;
// 文件存放地址
@property (nonatomic, strong) NSString *documentsDirectory; @property (nonatomic, strong) NSString *boundary;
@property (nonatomic, strong) NSString *fileParam;
@property (nonatomic, strong) NSURL *uploadURL;
@property (nonatomic, strong) NSNumber *currentIndex; @end @implementation ViewController - (void)initUploadList{
self.arrUploadList = [[NSMutableArray alloc] init];
NSArray *fileList = [self getFiles:self.documentsDirectory]; for(NSString* file in fileList)
{
NSString* filePath = [self getFilePath:file];
[self.arrUploadList addObject:[[FileUploadInfo alloc] initWithFileTitle:file andFilePath:filePath]];
} } // 继承tableview的函数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.arrUploadList.count ;
} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60.0;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"idCell"];
if( cell == nil ){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"idCell" ];
}
FileUploadInfo *uploader = [self.arrUploadList objectAtIndex:indexPath.row];
UILabel *title = (UILabel *)[cell viewWithTag:CellLabelTagValue];
// 设置属性
title.text = uploader.fileTitle;
return cell ;
} - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.isDoing = NO ; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentsDirectory = [paths objectAtIndex:];
self.tblFiles.delegate = self ;
self.tblFiles.dataSource = self ; [self initUploadList];
[self BgUploadInitSession]; } // -------------<feixiang>后台传输函数---------- - (void)BgUploadInitSession{
// 这里加入后台下载功能
// https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.yuanfang"];
// 后台下载用 backgroundSessionConfiguration,先用默认的设置
//NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; //sessionConfiguration.HTTPMaximumConnectionsPerHost = 5;
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil]; // 初始化上传地址
self.boundary = @"----------V2ymHFg03ehbqgZCaKO6jy" ;
self.uploadURL = [NSURL URLWithString:@"http://xxxx/Upload/"]; } - (NSMutableURLRequest *)BgUploadSetHeader{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:self.uploadURL];
[request setHTTPMethod:@"POST"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", self.boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"]; return request ;
} - (NSURL *)BgUploadSetUrl:(NSString *)uploadFilePath{
NSData *body = [self BgUploadPrepareData:uploadFilePath] ;
NSString* uploadFile_tmp = [NSString stringWithFormat:@"%@_tmp" ,uploadFilePath ];
[body writeToFile:uploadFile_tmp atomically:true]; // 上传完成后需要将临时文件删除
NSString *filePath = [[NSString stringWithFormat:@"file://%@", uploadFile_tmp] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *fileUrl = [NSURL URLWithString:filePath]; return fileUrl;
} // 这里删除文件有点问题
- (void)BgUploadRemoveTmpFile:(NSString *)tmpFilepath{
tmpFilepath = [NSString stringWithFormat:@"%@_tmp",tmpFilepath];
tmpFilepath = [[NSString stringWithFormat:@"file://%@", tmpFilepath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSFileManager *defaultManager;
defaultManager = [NSFileManager defaultManager];
NSError *error ;
BOOL ret = [defaultManager removeItemAtPath:tmpFilepath error:&error];
if( ret == NO )
NSLog(@"\nerror:%@",error);
} - (NSData*) BgUploadPrepareData:(NSString *)filePath
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:filePath]; NSMutableData *body = [NSMutableData data];
if( fileExists == YES ){
NSString *fileName = [filePath lastPathComponent]; NSData *dataOfFile = [[NSData alloc] initWithContentsOfFile:filePath]; // 组装POST格式
if (dataOfFile) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", self.boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/zip\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:dataOfFile];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", self.boundary] dataUsingEncoding:NSUTF8StringEncoding]];
}
return body;
} - (void)BgUploadCommon:(NSString *)uploadFilePath{
// 由于fromFile会覆盖原来的http请求的body内容。可以先构造一个request,然后将body信息存到文件里面,提供给task调用
// 1 , 构造 HTTP Request POST HEADER
NSMutableURLRequest *request = [self BgUploadSetHeader];
// 2 , 将文件和保存文件form-data信息一起保存到磁盘临时文件中
NSURL *fileUrl = [self BgUploadSetUrl:uploadFilePath];
// 3,使用task的fromFile上传函数
self.task = [self.session uploadTaskWithRequest:request fromFile:fileUrl];
// 启动后台任务,下面回调函数接收消息
[self.task resume];
}
// ----------end 后台传输-------- //----------------各个按钮事件
- (IBAction)startAll:(id)sender{
if( self.isDoing == NO ){
[self.buttonStart setTitle:@"STOP" forState:UIControlStateHighlighted];
self.isDoing = YES;
}else{
[self.buttonStart setTitle:@"START" forState:UIControlStateHighlighted];
self.isDoing = NO;
}
FileUploadInfo *uploader = [self.arrUploadList objectAtIndex:];
[self BgUploadCommon:uploader.filePath];
}
- (IBAction)stopUpload:(id)sender{
if( self.task.state == NSURLSessionTaskStateRunning ){
[self.task suspend];
}
}
- (IBAction)resumeUpload:(id)sender{
if( self.task.state == NSURLSessionTaskStateRunning ){
[self.task resume];
}
} - (IBAction)cancelUpload:(id)sender{
if( self.task.state == NSURLSessionTaskStateRunning ){
[self.task cancel];
}
} //----------------NSURLSession回调函数-------------------------
// 上传进度中
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSLog(@"\n%f / %f", (double)totalBytesSent,
(double)totalBytesExpectedToSend); // 更新界面
//int index = [self getIndexWithTaskIdentifier:task.taskIdentifier];
int index = [self.currentIndex intValue];
FileUploadInfo *uploader = [self.arrUploadList objectAtIndex:index]; [[NSOperationQueue mainQueue] addOperationWithBlock:^{
uploader.progress = (double)totalBytesSent / (double)totalBytesExpectedToSend; UITableViewCell *cell = [self.tblFiles cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:]];
UIProgressView *progressView = (UIProgressView *)[cell viewWithTag:CellProgressBarTagValue];
progressView.progress = uploader.progress;
}];
} // 上传完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
// 这里继续做下一个任务
[self BgUploadBeginNextTask];
} - (void)BgUploadBeginNextTask{
//int index = [self getIndexWithTaskIdentifier:task.taskIdentifier] + 1 ;
self.currentIndex = @([self.currentIndex intValue] + );
int index = [self.currentIndex intValue];
FileUploadInfo *uploader = [self.arrUploadList objectAtIndex:index]; NSLog(@"\n第 %@ 个任务 %@ 完成 ",self.currentIndex, uploader.filePath); UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = [NSString stringWithFormat:@"%@ have been uploaded!",uploader.filePath];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; //先删除临时文件
[self BgUploadRemoveTmpFile:uploader.filePath];
if( index < [self.arrUploadList count] ){
[self BgUploadCommon:uploader.filePath];
}
} // 后台传输完成,处理URLSession完成事件
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; // Check if all download tasks have been finished.
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([uploadTasks count] == ) {
if (appDelegate.backgroundTransferCompletionHandler != nil) {
// Copy locally the completion handler.
void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler; // Make nil the backgroundTransferCompletionHandler.
appDelegate.backgroundTransferCompletionHandler = nil; [[NSOperationQueue mainQueue] addOperationWithBlock:^{
completionHandler(); // 这里继续做下一个任务
[self BgUploadBeginNextTask];
}];
}
} }];
} -(int)getIndexWithTaskIdentifier:(unsigned long)taskIdentifier{
int index = ;
for (int i=; i<[self.arrUploadList count]; i++) {
FileUploadInfo *uploader = [self.arrUploadList objectAtIndex:i];
if (uploader.taskIdentifier == taskIdentifier) {
index = i;
break;
}
} return index;
} //----------------END NSURLSession回调函数----------------------- // 获取目录下的所有文件
-(NSArray*)getFiles:(NSString *)dir
{
NSFileManager* fm = [NSFileManager defaultManager];
NSArray* array = [fm contentsOfDirectoryAtPath:dir error:nil ];
NSMutableArray* fileList = [[NSMutableArray alloc]init]; BOOL isDir = NO ;
for(NSString* file in array)
{
[fm fileExistsAtPath:file isDirectory:&isDir];
if( !isDir && ![file isEqualToString:@".DS_Store"])
[fileList addObject:file];
}
return fileList ;
} - (NSString*)getFilePath:(NSString *)filename{
NSString *uploadFilePath = [self.documentsDirectory stringByAppendingPathComponent:filename];
return uploadFilePath;
} - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end

http://numbbbbb.gitbooks.io/-the-swift-programming-language-/

ios NSURLSession后台传输的更多相关文章

  1. iOS 后台传输服务

    后台传输服务 — 我们用水壶来比喻 (0:14) 后天传输服务是 iOS 7 引进的 API,它准许应用暂停或者中止之后,在后台继续执行网络服务(比如下载或者上传).举个例子,这正是 Dropbox ...

  2. iOS - NSURLSession 网络请求

    前言 NS_CLASS_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0) @interface NSURLSession : NSObject @available(iOS ...

  3. iOS设备后台播放音乐方法

    iOS设备后台播放音乐方法 1 在设置Capabliites中打开Background Modes,选择Audio And AirPlay 2 在控制viewDidLoad中添加下面代码 AVAudi ...

  4. [ExtJS5学习笔记]第第二十四次 Extjs5形式上gridpanel或表单数据后台传输remoteFilter设定

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39667533 官方文档:http://docs.sencha.com/extjs/5. ...

  5. [ExtJS5学习笔记]第二十四节 Extjs5中表格gridpanel或者表单数据后台传输remoteFilter设置

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39667533 官方文档:http://docs.sencha.com/extjs/5. ...

  6. IOS微信后台运行时候倒计时暂停问题

    链接:https://pan.baidu.com/s/1i7cSkqL 密码:g80i 最近给央视做了个H5答题游戏,但在倒计时上遇到一个终端问题:手机端按Home键将微信收入后台之后,IOS11 会 ...

  7. IOS的后台执行

    写在前面给大家推荐一个不错的站点  www.joblai.com 本文章由央广传媒开发部 冯宝瑞整理.哈哈 http://www.cocoachina.com/bbs/read.php? tid=14 ...

  8. ios NSURLSession(iOS7后,取代NSURLConnection)使用说明及后台工作流程分析

    NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作.注意, ...

  9. ios NSURLSession使用说明及后台工作流程分析

    NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作.注意, ...

随机推荐

  1. Codeblocks 常用快捷键

    编辑部分: Ctrl + A:全选Ctrl + C:复制Ctrl + X: 剪切Ctrl + V:粘贴Ctrl + Z:撤销Ctrl + S:保存Ctrl + Y / Ctrl + Shift + Z ...

  2. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

  3. java注解的概念理解

    1. 注解(标注)概念:从字面意思理解是对被标注的对象(类,接口,枚举,注解类,方法,参数)的一个标记,有这个标记有什么用呢?就像学习中“划重点”的方式一样,被标记的对象肯定是特殊需要特别关照的对象, ...

  4. String、StringBuffer和StringBulder

    String:不可改变的Unicode字符序列. 池化思想,把需要共享的数据放在池中,用一个存储区域来存放一些公用资源以减少存储空间的开销. 在String类中,以字面值创建时,会到Java方法空间的 ...

  5. UltraISO制作U盘启动盘安装Win7系统攻略

    reference win 7 iso name: cn_windows_7_ultimate_x86_dvd_x15-65907.iso URL FOR download: http://jingy ...

  6. 各种梯度下降 bgd sgd mbgd adam

    转载  https://blog.csdn.net/itchosen/article/details/77200322 各种神经网络优化算法:从梯度下降到Adam方法     在调整模型更新权重和偏差 ...

  7. python单元测试模块unittest

    1.unittest_demo.py # coding=utf-8 import time import unittest from HtmlTestRunner import HTMLTestRun ...

  8. Python3高级基础(2)

    1 Python3模拟数据结构 1.1 栈 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表.栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进 ...

  9. [BOI2004]Sequence 数字序列

    Description: Hint: \(n<=10^5\) Solution: 首先考虑b不严格递增时的做法 发现当\(a[i]\)递增时\(b[i]\)直接取\(a[i]\)即可,否则此时需 ...

  10. Hive总结(八)Hive数据导出三种方式

    今天我们再谈谈Hive中的三种不同的数据导出方式. 依据导出的地方不一样,将这些方式分为三种: (1).导出到本地文件系统. (2).导出到HDFS中: (3).导出到Hive的还有一个表中. 为了避 ...