ios NSURLSession后台传输
http://www.appcoda.com/background-transfer-service-ios7/
http://www.raywenderlich.com/51127/nsurlsession-tutorial
http://blog.csdn.net/kyfxbl/article/details/18629227
http://hayageek.com/ios-nsurlsession-example/
一个很好的IOS学习网站:
遇到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后台传输的更多相关文章
- iOS 后台传输服务
后台传输服务 — 我们用水壶来比喻 (0:14) 后天传输服务是 iOS 7 引进的 API,它准许应用暂停或者中止之后,在后台继续执行网络服务(比如下载或者上传).举个例子,这正是 Dropbox ...
- iOS - NSURLSession 网络请求
前言 NS_CLASS_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0) @interface NSURLSession : NSObject @available(iOS ...
- iOS设备后台播放音乐方法
iOS设备后台播放音乐方法 1 在设置Capabliites中打开Background Modes,选择Audio And AirPlay 2 在控制viewDidLoad中添加下面代码 AVAudi ...
- [ExtJS5学习笔记]第第二十四次 Extjs5形式上gridpanel或表单数据后台传输remoteFilter设定
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39667533 官方文档:http://docs.sencha.com/extjs/5. ...
- [ExtJS5学习笔记]第二十四节 Extjs5中表格gridpanel或者表单数据后台传输remoteFilter设置
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39667533 官方文档:http://docs.sencha.com/extjs/5. ...
- IOS微信后台运行时候倒计时暂停问题
链接:https://pan.baidu.com/s/1i7cSkqL 密码:g80i 最近给央视做了个H5答题游戏,但在倒计时上遇到一个终端问题:手机端按Home键将微信收入后台之后,IOS11 会 ...
- IOS的后台执行
写在前面给大家推荐一个不错的站点 www.joblai.com 本文章由央广传媒开发部 冯宝瑞整理.哈哈 http://www.cocoachina.com/bbs/read.php? tid=14 ...
- ios NSURLSession(iOS7后,取代NSURLConnection)使用说明及后台工作流程分析
NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作.注意, ...
- ios NSURLSession使用说明及后台工作流程分析
NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnection可以互为替代工作.注意, ...
随机推荐
- gulp给文件加版本号
版本号用文件MD5生成 默认根据文件MD5生成,因此文件未发生改变,此版本号将不会变 所以当没有改变文件的时候,我们就不能用gulp来改变版本号了 需要安装的插件 npm install --save ...
- Python列表split方法
转载自:https://www.cnblogs.com/douzi2/p/5579651.html 1.split翻译为分裂. split()就是将一个字符串分裂成多个字符串组成的列表. 2.spl ...
- 007 关于Spark下的第二种模式——standalone搭建
一:介绍 1.介绍standalone Standalone模式是Spark自身管理资源的一个模式,类似Yarn Yarn的结构: ResourceManager: 负责集群资源的管理 NodeMan ...
- 桌面版centos安装vncserver并在windows下使用VNC Viewer远程连接
首先关闭防火墙 在Centos中安装vncserver yum install tigervnc-server 拷贝一份 /lib/systemd/system/vncserver@.service ...
- jackson实现java对象转支付宝/微信模板消息
一.支付宝消息模板大致长这样 { "to_user_id": "", "telephone": "xxxxx", &qu ...
- SQLite中SELECT基本形式
SQLite中SELECT基本形式 每个数据库通常都包含多个表,而每个表又包含多条数据.要获取数据库中的数据,就需要SQL语言提供的查询语句SELECT.本章将讲解和SELECT语句相关的内容,其中包 ...
- Log4j教程
Log4j教程 一.快速上手 log4j把日志分为:all,trace,debug,info,warnig,error,fital,off等几个级别.级别高的会屏蔽级别的的信息. 1)maven导入j ...
- 潭州课堂25班:Ph201805201 WEB 之 页面编写 第三课 (课堂笔记)
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- C++ 模板应用举例_模板实现STL类(堆栈)
//stack集合类是一个简单的堆栈的实现. //这里有两个模板参数,T和size,指定堆栈中的元素类型和堆栈中项数的最大值. //push 和 pop成员函数添加和删除堆栈中的项,并在堆栈底部增加. ...
- 【洛谷】1600:天天爱跑步【LCA】【开桶】【容斥】【推式子】
P1600 天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个 ...