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. Linux环境下Node.js的安装配置

    1.   官网下载Node.js 2.   安装Node.js 根据下载内容的不同,提供三种安装方法,选择自己喜欢的方式 2.1.   绿色免安装版(Linux(.tar.gz)) 解压Node-XX ...

  2. AOJ 0005 GCD and LCM

    题意:求两数最大公约数和最小公倍数. 类型:辗转相除法 算法:gcd(a,b)=gcd(b,a%b),lcm(a,b)=a*b/gcd(a,b). #include <cstdio> #i ...

  3. POJ2891 Strange Way to Express Integers 扩展欧几里德 中国剩余定理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ2891 题意概括 给出k个同余方程组:x mod ai = ri.求x的最小正值.如果不存在这样的x, ...

  4. Java内存模型及Java关键字 volatile的作用和使用说明

    先来看看这个关键字是什么意思:volatile  [ˈvɒlətaɪl] adj. 易变的,不稳定的; 从翻译上来看,volatile表示这个关键字是极易发生改变的.volatile是java语言中, ...

  5. iOS 技术篇: 如何利用dsym文件分析苹果被拒日志

    今天提审被拒了.伤心

  6. python的常用模块之collections模块

    python的常用模块之collections模块 python全栈开发,模块,collections 认识模块 什么是模块?    常见的场景:一个模块就是一个包含了python定义和声明的文件,文 ...

  7. flask-include标签使用标签

      [footer.html] <footer> 这是底部 </footer> [header.html] <style> .nav ul{ overflow: h ...

  8. html 音乐 QQ播放器 外链 代码 播放器 外链 代码

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha QQ播放器 外链 代码 播放器 外链 代码 ======== 歌曲链接 QQ播放器 外链 ...

  9. Codeforces.547D.Mike and Fish(思路 欧拉回路)

    题目链接 \(Description\) 给定平面上n个点,将这些点染成红or蓝色,要求每行.每列红色点与蓝色点数量的差的绝对值<=1.输出方案(保证有解). \(Solution\) 参考这 ...

  10. CodeForces903G Yet Another Maxflow Problem 扫描线 + 线段树 + 最小割

    给定两条链\(A, B\),其中\(A\)链某些点向\(B\)链有连边,支持修改\(A\)链中的某条边权以及查询\(A_1\)到\(B_n\)的最大流 显而易见,\(A\)和\(B\)链中一定满足左部 ...