您的位置:首页 > 移动开发 > Swift

IOS开发Swift使用NSURLSessionUploadTask实现后台上传功能

2016-04-19 16:44 681 查看
服务器的前端用的是nginx 后端是tocat,具体不知什么个原理没有接触,不过nginx是支持我这样上传的

1.代码类:

//
//  JPCUploadHelper.swift
//  joopic
//
//  Created by jianxiong li on 16/4/9.
//  Copyright © 2016年 joobot. All rights reserved.
//

import Foundation

protocol JPCUploadStatusDelegate{
func  bytesSent(key:String,bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64);
func  complete(key:String,error:NSError?,jesionStr:String?);
}

var upHelpers:NSMutableDictionary = NSMutableDictionary()

class JPCUploadHelper:NSObject{

var session:NSURLSession?
var delegate:JPCUploadStatusDelegate?
var key:String!

var backgroundCompletionHandler:(()->())?

private static let JPC_UPLOAD_IDENTIFIER_PRE:String = "IDENTIFIER_PRE"

let boundary = "AF0xKhTmLbOuNdArY"

class func uploadHelper(key:String)->JPCUploadHelper{
let identifier = "\(JPC_UPLOAD_IDENTIFIER_PRE)_\(key)"
let helper:JPCUploadHelper? = upHelpers.objectForKey(identifier) as? JPCUploadHelper
print("===============================uploadHelper.......helper:\(helper)")
if(helper == nil){
return JPCUploadHelper(key: key)
}else{
return helper!
}
}

class func hasUploadHelper(identifier:String)->JPCUploadHelper?{
let helper:JPCUploadHelper? = upHelpers.objectForKey(identifier) as? JPCUploadHelper
return helper
}

//指定构造器
private init(key:String){
super.init()
self.key = key
if(self.session == nil){
let identifier = self.getIdentifier(key)
let config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(identifier)

//config.discretionary = true
config.allowsCellularAccess = SafeUtil.getBoolean(KEY_SAVE_IMAGE_ON_2G_3G_NET, delf: false)//是否允许使用蜂窝连接
//print("JPCDownloadHelper init.......config.allowsCellularAccess:\(config.allowsCellularAccess) config.discretionary:\(config.discretionary)")

self.session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
upHelpers.setObject(self, forKey: identifier)
}
}

private func getRequest(url:NSURL)->NSMutableURLRequest{

let req = NSMutableURLRequest(URL: url)

//1 MARK: >必须加参数  时间戳和鉴权 已经省略
//req.setValue("Bearer \(base64String!)", forHTTPHeaderField: "Authorization")
req.HTTPMethod = "POST"

//  Add the header info
req.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

return req
}

//这个方法可能改成中上传一个图片的方法,去掉参数midFilepath  minFilePath
//->2 Uploading Body Content Using a Stream 使用uploadTaskWithStreamedRequest(request) 上传
func uploadFile(ObjectFilePath: String,MidFilePath: String,MinFilePath: String,var reqURL:NSURL?,delegate:JPCUploadStatusDelegate){
print("===========================================================================================")
if(reqURL == nil){
reqURL = NSURL(string:  "这里是上传的https地址")!
}

self.delegate = delegate

print("1 JPCUploadManager uploadFileUseFormFile key:\(key)  url:\(reqURL)")

// 1 > create the URL POST Request
let request:NSMutableURLRequest = getRequest(reqURL!)

// 2 >  将文件和保存文件form-data信息一起保存到磁盘临时文件中
let fileUrl = self.saveFormWithFile2DiskFile(key, ObjectFilePath: ObjectFilePath, MidFilePath: MidFilePath, MinFilePath: MinFilePath)

print("4 JPCUploadManager uploadFileUseFormFile fileUrl:\(fileUrl) ")
// 3 > 上传
let uploadTask = self.session!.uploadTaskWithRequest(request, fromFile: fileUrl)
uploadTask.taskDescription = self.key

uploadTask.resume()

}

}

extension JPCUploadHelper:NSURLSessionDelegate{

//->1 pragma mark - NSURLSessionDelegate implementation
@objc func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
print("JPCUploadManager NSURLSessionDelegate didBecomeInvalidWithError............error:\(error) session:\(session) identifier:\(session.configuration.identifier!)")
}

//挑战处理类型为 默认
/*
NSURLSessionAuthChallengePerformDefaultHandling:默认方式处理
NSURLSessionAuthChallengeUseCredential:使用指定的证书
NSURLSessionAuthChallengeCancelAuthenticationChallenge:取消挑战
*/
//->2 pragma mark - NSURLSessionDelegate implementation
@objc func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {

let credential:NSURLCredential? = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)

print("JPCUploadManager NSURLSessionDelegate  didReceiveChallenge---------- challenge:\(challenge) completionHandler:\(completionHandler) credential:\(credential)")
// 确定挑战的方式
var disposition = NSURLSessionAuthChallengeDisposition.UseCredential
if (credential != nil) {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential;
} else {
disposition = NSURLSessionAuthChallengeDisposition.PerformDefaultHandling;
}

// 必须调用此方法,完成认证挑战
completionHandler(disposition,credential)
}

//->3 pragma mark - NSURLSessionDelegate implementation
@objc func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) {

let completionhandler = self.backgroundCompletionHandler
self.backgroundCompletionHandler = nil

print("JPCUploadManager NSURLSessionDelegate URLSessionDidFinishEventsForBackgroundURLSession completionhandler:\(completionhandler) session:\(session) ")

dispatch_async(dispatch_get_main_queue(), {
completionhandler?()
})

self.session?.invalidateAndCancel()
helpers.removeObjectForKey(session.configuration.identifier!)

}

func URLSession(session: NSURLSession, task: NSURLSessionTask, needNewBodyStream completionHandler: (NSInputStream?) -> Void) {
print("JPCUploadManager NSURLSessionDelegate needNewBodyStream task:\(task) ")
}
}

extension JPCUploadHelper:NSURLSessionTaskDelegate{
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {

let credential:NSURLCredential? = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
print("JPCUploadManager NSURLSessionTaskDelegate didReceiveChallenge---------- challenge:\(challenge) completionHandler:\(completionHandler) credential:\(credential) task:\(task)")

var disposition = NSURLSessionAuthChallengeDisposition.UseCredential
// 确定挑战的方式
if (credential != nil) {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential;
} else {
disposition = NSURLSessionAuthChallengeDisposition.PerformDefaultHandling;
}

// 必须调用此方法,完成认证挑战
completionHandler(disposition,credential)
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
print("JPCUploadManager NSURLSessionTaskDelegate  didSendBodyData---------- bytesSent:\(bytesSent) totalBytesSent:\(totalBytesSent) totalBytesExpectedToSend:\(totalBytesExpectedToSend) task.taskDescription:\(task.taskDescription!)")
//print("session:\(session) task:\(task)  ")

let key = task.taskDescription

if( key != nil){

self.delegate?.bytesSent(key!,bytesSent: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend)

}

}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
print("JPCUploadManager NSURLSessionTaskDelegate didCompleteWithError...error:\(error).session:\(session) task:\(task) ")
let key = task.taskDescription

if( error != nil && key != nil){
self.delegate?.complete(key!,error: error,jesionStr:nil)
self.deleFormWithFileFromDisk()

}

}

func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest?) -> Void) {
print("JPCUploadManager willPerformHTTPRedirection  needNewBodyStream............")
}

}

extension JPCUploadHelper:NSURLSessionDataDelegate{
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
print("JPCUploadManager NSURLSessionDataDelegate didReceiveResponse  ............response:\(response) expectedContentLength:\(response.expectedContentLength)")
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {

let strData = NSString(data: data, encoding: NSUTF8StringEncoding)
let key = dataTask.taskDescription

print("JPCUploadManager NSURLSessionDataDelegate didReceiveData ============================session:\(session).dataTask:\(dataTask) key:\(key)")
print("JPCUploadManager NSURLSessionDataDelegate didReceiveData  ===========================strData:\(strData)")

if( key != nil){

print("JPCUploadManager NSURLSessionDataDelegate didReceiveData  ===========================delegate:\(self.delegate)")
self.delegate?.complete(key!,error:nil,jesionStr:String(strData))

upHelpers.removeObjectForKey(self.key)
self.deleFormWithFileFromDisk()
}

}
}

extension JPCUploadHelper{

func getIdentifier(key:String)->String{
return "\(JPCUploadHelper.JPC_UPLOAD_IDENTIFIER_PRE)_\(key)"
}
}

extension JPCUploadHelper{

func deleFormWithFileFromDisk(){
let uploadFileTemp = CommonUitl.getUploadFileTempPath().stringByAppendingString("/\(key)_for_upload_tmp")
let fileManager = NSFileManager.defaultManager()
if(fileManager.fileExistsAtPath(uploadFileTemp)){
do {
try fileManager.removeItemAtPath(uploadFileTemp)
print(" deleFormWithFileFromDisk ok path: \(uploadFileTemp)")
} catch let error as NSError {
print(" deleFormWithFileFromDisk ERROR: \(error)")
}

}
}

//1 将带有file数据的表单 存为文件
func saveFormWithFile2DiskFile(key:String,uploadFilePath:String)->NSURL{
let body = repareFormData(uploadFilePath)

//        let fileName = (uploadFilePath as NSString).lastPathComponent
//        let uploadFileTemp = CommonUitl.getUploadFileTempPath().stringByAppendingString("/\(fileName)_\(key)_upload_tmp")

let uploadFileTemp = CommonUitl.getUploadFileTempPath().stringByAppendingString("/\(key)_for_upload_tmp")

print("saveFormWithFile2DiskFile uploadFileTemp:\(uploadFileTemp) body.lentgh:\(body.length)")

return execSaveData(body, uploadFileTemp: uploadFileTemp)
}

//2 将带有file数据的表单 存为文件
func saveFormWithFile2DiskFile(key:String,ObjectFilePath: String,MidFilePath: String,MinFilePath: String)->NSURL{

let body = repareFormData(ObjectFilePath,MidFilePath: MidFilePath,MinFilePath: MinFilePath)

let uploadFileTemp = CommonUitl.getUploadFileTempPath().stringByAppendingString("/\(key)_for_upload_tmp")

print("saveFormWithFile2DiskFile uploadFileTemp:\(uploadFileTemp) body.lentgh:\(body.length)")

return execSaveData(body, uploadFileTemp: uploadFileTemp)

}

func execSaveData(body:NSData,uploadFileTemp:String)->NSURL{

let fileManger = NSFileManager.defaultManager()
do {

if(fileManger.fileExistsAtPath(uploadFileTemp)){
try fileManger.removeItemAtPath(uploadFileTemp)
}

} catch let error as NSError {
print("saveFormWithFile2DiskFile remove ERROR: \(error)")
}

body.writeToFile(uploadFileTemp, atomically: true)

if(fileManger.fileExistsAtPath(uploadFileTemp)){
print("saveFileInForm2FormFile save ok path: \(uploadFileTemp)")
}

let fileUrl = NSURL(fileURLWithPath: uploadFileTemp)
return fileUrl
}

//1 将文件数据组装到form表单中
func repareFormData(filePath:String)->NSData{

var body = NSMutableData()

// 参数
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"ObjectType\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("picture\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

// 参数
self.appdFile(&body, FilePath: filePath)

// 结尾
body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

return body
}

// 2 将文件数据组装到form表单中
func repareFormData(ObjectFilePath: String,MidFilePath: String,MinFilePath: String)->NSData{

var body = NSMutableData()

// 参数
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"ObjectType\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("picture\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

// 参数
self.appdFile(&body, FilePath: ObjectFilePath)

// 参数
self.appdFile(&body, FilePath: MidFilePath)

// 参数
self.appdFile(&body, FilePath: MinFilePath)

// 结尾
body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

return body
}

private func appdFile(inout body:NSMutableData,FilePath: String){

let fileManager = NSFileManager.defaultManager()

if(fileManager.fileExistsAtPath(FilePath)){

if let dataOfFile = NSData(contentsOfFile: FilePath) {

let fileName = (FilePath as NSString).lastPathComponent
let ext = (fileName as NSString).pathExtension
let type = ext == "png" ? "image/png" : "image/jpeg"

print("JPCUploadManager appdFile ext:\(ext) type:\(type)")

// 参数
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"ObjectFile\"; filename=\"\(fileName)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: \(type)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(dataOfFile)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

}

}
}

}


第二,使用:

//后台下载上传功能
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
print("application handleEventsForBackgroundURLSession identifier:\(identifier) completionHandler:\(completionHandler)")

let h = JPCUploadHelper.hasUploadHelper(identifier)
if(h != nil){
h!.backgroundCompletionHandler = completionHandler
}

}


extension MeInfoViewController:JPCUploadStatusDelegate{

func test(gotImage:UIImage){
let data:NSData = UIImagePNGRepresentation(gotImage)!
//        let fileURL = MeinfoUtils.saveImg2Sdcard(data, fileName: "test.png"

let filePath = CommonUitl.getDocumentsPath()+"/testtest.png"
data.writeToFile(filePath, atomically: true)

print("afterCropperImage ============ test filePath:\(filePath)  imageSize:\(data.length)")

let manager = NSFileManager.defaultManager()
if(manager.fileExistsAtPath(filePath)){
print("afterCropperImage ============ test save ok filePath:\(filePath)")
}
JPCUploadHelper.uploadHelper("keytest").uploadFile(filePath, MidFilePath: filePath, MinFilePath: filePath, reqURL: nil, delegate: self)

let filePath2 = CommonUitl.getDocumentsPath()+"/testtest2.png"
data.writeToFile(filePath2, atomically: true)

if(manager.fileExistsAtPath(filePath2)){
print("afterCropperImage ============ test save ok filePath:\(filePath2)")
}
JPCUploadHelper.uploadHelper("keytest2").uploadFile(filePath2, MidFilePath: filePath2, MinFilePath: filePath2, reqURL: nil, delegate: self)

}

func complete(key: String, error: NSError?, jesionStr: String?) {
print("--------------------------------:\(key) jesonStr:\(jesionStr)")
}

func bytesSent(key: String, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
print("--------------------------------:\(key) totalBytesSent:\(totalBytesSent) totalBytesExpectedToSend:\(totalBytesExpectedToSend)")
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: