Background upload multiple images using one NSURLSession uploadTaskWithRequest

I want to upload multiple images in the background using a single uploadTaskWithRequest method. When trying to execute the following code: Downloading tasks from NSData is 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)\r\n") body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n") body.appendString("\(value)\r\n") } } 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)\r\n") body.appendString("Content-Disposition: form-data; name=\"\(self.filePathKey)\"; filename=\"\(filename)\"\r\n") body.appendString("Content-Type: \(mimetype)\r\n\r\n") body.appendData(data!) body.appendString("\r\n") i += 1; } body.appendString("--\(boundary)--\r\n") // 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(); } 
+7
ios background swift nsurlsession
source share
1 answer

To load into a background session, the data must first be saved in a file.

You can also handle downloads that end while the application is in the background.

To simplify management, create one NSURLSession for each boot task, each with a unique identifier.

For more information on implementation details, see the URL Programming Guide .

AppDelegate example:

 @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. } } 

To load multiple images in one request, the images must first be encoded in the multipart / formdata MIME type, as you did. The difference is that all of this MIME message must be saved in one file, which is the file that is uploaded to the server.

Here is an example that shows how to do this. It works by serializing parts of MIME directly to a file. You can also create a message in NSData, although you run the risk of encountering restrictions when working with 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 = "\r\n" 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) } 
+10
source share

All Articles