后台使用单个 NSURLSession uploadTaskWithRequest 上传多张图片

编程入门 行业动态 更新时间:2024-10-20 01:31:25
本文介绍了后台使用单个 NSURLSession uploadTaskWithRequest 上传多张图片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想使用单个 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.

  • 使用 writeToFile:options:.
  • 调用 NSURLSession uploadTaskWithRequest:fromFile: 创建任务.请注意,请求中不能包含 HTTPBody 中的数据,否则上传会失败.
  • 在 URLSession:didCompleteWithError: 委托方法.
  • Save the data to file using writeToFile:options:.
  • Call NSURLSession uploadTaskWithRequest:fromFile: to create the task. Note that the request must not contain the data in the HTTPBody otherwise the upload will fail.
  • Handle completion in the URLSession:didCompleteWithError: delegate method.
  • 您可能还想处理应用在后台时完成的上传.

    You may also want to handle uploads which complete while the app is in the background.

  • 实现 application:handleEventsForBackgroundURLSession:completionHandler 在 AppDelegate 中.
  • 使用提供的标识符创建一个 NSURLSession.
  • 按照通常的上传响应委托方法(例如处理 URLSession:didCompleteWithError:)
  • 调用 URLSessionDidFinishEventsForBackgroundURLSession 完成事件处理后.
  • Implement application:handleEventsForBackgroundURLSession:completionHandler in the AppDelegate.
  • Create an NSURLSession with the provided identifier.
  • Respond to the delegate methods as per a usual upload (e.g. handle the response in URLSession:didCompleteWithError:)
  • Call URLSessionDidFinishEventsForBackgroundURLSession when you have completed processing the event.
  • 为了更容易管理,为每个上传任务创建一个 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 上传多张图片

    本文发布于:2023-11-26 02:52:01,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1632344.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:多张   后台   上传   图片   uploadTaskWithRequest

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!