我想使用单个 uploadTaskWithRequest 方法在后台上传多张图片.在尝试以下代码时,后台会话不支持来自 NSData 的上传任务...请问如何实现这一点
I want to upload multiple images in background using a single uploadTaskWithRequest method. While trying the following code returns Upload tasks from NSData are not supported in background sessions...please how to achieve this
func createRequest (param : NSDictionary ,imagearray :NSMutableArray, strURL : String) -> NSURLRequest { let boundary = generateBoundaryString() let url = NSURL(string: strURL) let request = NSMutableURLRequest(URL: url!) request.setValue("multipart/form-data; boundary=(boundary)", forHTTPHeaderField: "Content-Type") request.HTTPMethod = "POST" request.HTTPBody = createBodyWithParameters(param, image_array:imagearray,boundary: boundary); return request } func createBodyWithParameters(parameters: NSDictionary,image_array:NSMutableArray,boundary: String) -> NSData { let body = NSMutableData() for (key, value) in parameters { if(value is String || value is NSString){ body.appendString("--(boundary) ") body.appendString("Content-Disposition: form-data; name="(key)" ") body.appendString("(value) ") } } var i = 0; for image in image_array { let filename = "image(i).jpg" let data = UIImagePNGRepresentation(image as! UIImage); let mimetype = "image/png" body.appendString("--(boundary) ") body.appendString("Content-Disposition: form-data; name="(self.filePathKey)"; filename="(filename)" ") body.appendString("Content-Type: (mimetype) ") body.appendData(data!) body.appendString(" ") i += 1; } body.appendString("--(boundary)-- ") // NSLog("data %@",NSString(data: body, encoding: NSUTF8StringEncoding)!); return body } func postrequestwithformdata(requesturl:String,postparams:NSDictionary,postformadata:NSMutableArray,requestId:Int) { self.requestid = requestId; let requestformdata = self.createRequest(postparams, imagearray: postformadata, strURL: requesturl); let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(Contants.identifier) let session: NSURLSession = NSURLSession(configuration:configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue()); let task: NSURLSessionUploadTask = session.uploadTaskWithRequest(requestformdata, fromData: requestformdata.HTTPBody!); task.resume(); } 推荐答案要在后台会话中上传,必须先将数据保存到文件中.
To upload in a background session, the data must first saved to a file.
您可能还想处理应用在后台时完成的上传.
You may also want to handle uploads which complete while the app is in the background.
为了更容易管理,为每个上传任务创建一个 NSURLSession,每个任务都有一个唯一的标识符.
To make this easier to manage, create one NSURLSession per upload task, each with a unique identifier.
参考URL 会话编程指南了解实现细节.
AppDelegate 示例:
Example AppDelegate:
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate { var window: UIWindow? typealias CompletionHandler = () -> Void var completionHandlers = [String: CompletionHandler]() var sessions = [String: NSURLSession]() func upload(request: NSURLRequest, data: NSData) { // Create a unique identifier for the session. let sessionIdentifier = NSUUID().UUIDString let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first! let fileURL = directoryURL.URLByAppendingPathComponent(sessionIdentifier) // Write data to cache file. data.writeToURL(fileURL, atomically: true); let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(sessionIdentifier) let session: NSURLSession = NSURLSession( configuration:configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue() ) // Store the session, so that we don't recreate it if app resumes from suspend. sessions[sessionIdentifier] = session let task = session.uploadTaskWithRequest(request, fromFile: fileURL) task.resume() } // Called when the app becomes active, if an upload completed while the app was in the background. func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: CompletionHandler) { let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(identifier) if sessions[identifier] == nil { let session = NSURLSession( configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue() ) sessions[identifier] = session } completionHandlers[identifier] = completionHandler } func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) { // Handle background session completion handlers. if let identifier = session.configuration.identifier { if let completionHandler = completionHandlers[identifier] { completionHandler() completionHandlers.removeValueForKey(identifier) } // Remove session sessions.removeValueForKey(identifier) } // Upload completed. } }要在单个请求中上传多个图像,必须首先将图像编码为 multipart/formdata MIME 类型,正如您所做的那样.不同之处在于整个 MIME 消息必须保存到单个文件中,该文件是上传到服务器的文件.
To upload multiple images in a single request, the images must first be encoded into the multipart/formdata MIME type, as you have done. The difference being that this entire MIME message must be saved to a single file, which is the file that is uploaded to the server.
这里是一个例子,展示了如何做到这一点.它通过将 MIME 部分直接序列化为文件来工作.您也可以在 NSData 中构建消息,尽管在处理大文件时可能会遇到内存限制.
Here is an example which shows how to do this. It works by serialising the MIME parts directly to a file. You could also build up the message in an NSData, although you risk running into memory limitations when handling large files.
func uploadImages(request: NSURLRequest, images: [UIImage]) { let uuid = NSUUID().UUIDString let boundary = String(count: 24, repeatedValue: "-" as Character) + uuid // Open the file let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first! let fileURL = directoryURL.URLByAppendingPathComponent(uuid) let filePath = fileURL.path! NSFileManager.defaultManager().createFileAtPath(filePath, contents: nil, attributes: nil) let file = NSFileHandle(forWritingAtPath: filePath)! // Write each image to a MIME part. let newline = " " for (i, image) in images.enumerate() { let partName = "image-(i)" let partFilename = "(partName).png" let partMimeType = "image/png" let partData = UIImagePNGRepresentation(image) // Write boundary header var header = "" header += "--(boundary)" + newline header += "Content-Disposition: form-data; name="(partName)"; filename="(partFilename)"" + newline header += "Content-Type: (partMimeType)" + newline header += newline let headerData = header.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) print("") print("Writing header #(i)") print(header) print("Writing data") print("(partData!.length) Bytes") // Write data file.writeData(headerData!) file.writeData(partData!) } // Write boundary footer var footer = "" footer += newline footer += "--(boundary)--" + newline footer += newline print("") print("Writing footer") print(footer) let footerData = footer.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) file.writeData(footerData!) file.closeFile() // Add the content type for the request to multipart. let outputRequest = request.copy() as! NSMutableURLRequest let contentType = "multipart/form-data; boundary=(boundary)" outputRequest.setValue(contentType, forHTTPHeaderField: "Content-Type") // Start uploading files. upload(outputRequest, fileURL: fileURL) }更多推荐
后台使用单个 NSURLSession uploadTaskWithRequest 上传多张图片
发布评论