IOS开发Swift使用NSURLSessionUploadTask实现后台上传功能
2016-04-19 16:44
681 查看
服务器的前端用的是nginx 后端是tocat,具体不知什么个原理没有接触,不过nginx是支持我这样上传的
1.代码类:
第二,使用:
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)") } }
相关文章推荐
- openstack swift页面安装
- iOS开发Swift UITableView和UICollectionView的使用
- Swift笔记:继承
- swift笔记2
- swift输入验证码提示框
- swift分装的倒计时按钮
- Swift UIFont 传入字体name和size问题
- Swift 下debug状态打印log
- Swift笔记:方法
- 自定义presentViewController的转场动画(Swift)
- Swift PageControl
- Swift -- 2.基本数据类型
- Swift UIDatePikcer
- swift-元组的基本用法
- Apple Swift编程语言入门教程
- swift和oc混编
- 趋势!SWIFT必定会被区块链技术取…
- SWIFT:必须承认区块链在金融行业…
- Swift提出“区块链路线图”,谋求突…
- 消息人士称,Google考虑将Swift作为安卓的主要编程语言