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. 关键字super和this的使用及区别

    "this"作为一个特殊的关键字,它的规则如下: 1.可以表示构造函数传递.this(a,b)表示调用另外一个构造函数.这里面的this就是一个特殊语法,不是变量,没有什么类型. ...

  2. zend studio调试

    XDdebug搞了我一天 先把php.ini的代码发一下 [XDebug] zend_extension = "d:/WAMP/wamp/bin/php/php5.5.12/zend_ext ...

  3. Dockerfile中ENTRYPOINT 和 CMD的区别

    一.dockerfile中的 CMD 1.每个dockerfile中只能有一个CMD如果有多个那么只执行最后一个. 2.CMD 相当于启动docker时候后面添加的参数看,举个简单例子: docker ...

  4. Rstudio+mysql写入中文表

    1.在mysql中输入sql语句,新建一个支持中文的数据库 create database Chinadaydata DEFAULT CHARACTER SET gbk COLLATE gbk_chi ...

  5. (转)MyBatis+MySQL 返回插入的主键ID

    MyBatis+MySQL 返回插入的主键ID 需求:使用MyBatis往MySQL数据库中插入一条记录后,需要返回该条记录的自增主键值. 方法:在mapper中指定keyProperty属性,示例如 ...

  6. (转)java代码发送JSON格式的httpPOST请求

    import Java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import j ...

  7. dp的最优性

    dp看似像递推,但是有一点不一样,虽然都是先处理完子过程并由此退出最终的,但是dp满足任何过程的最优性,dp用子过程最优来保证最终结果的最优性.

  8. IntelliJ IDEA 2018.3 重大升级(转)

    |0前言 2018.11.28 IntelliJ IDEA 2018.3 正式版发布.对于一个忠实爱好者,迫不及待的我下载了最新版本来体验下.而且 IDEA 今年的第三次重大更新提供了不容错过的显著功 ...

  9. php反序列化简叙

    0x01 php简单的反序列化 这题是在网上看到的,原题连接不太了解,但是源码题目给了出来,稍微下文件名和排版在本地测试 <?php class SoFun{ protected $file=' ...

  10. CSS-定位(Position)

    目录 CSS-定位(Position) CSS-定位(Position) ### 学习自 菜鸟教程 ### Overview CSS中HTML元素存在以下之后定位选项 Position Desc st ...