Per caricare in una sessione di sfondo, i dati deve prima salvato in un file.
- Salvare i dati su file utilizzando writeToFile:options:.
- Chiamare NSURLSession uploadTaskWithRequest:fromFile: per creare l'attività. Si noti che la richiesta non deve contenere i dati nello
HTTPBody
altrimenti il caricamento avrà esito negativo.
- Completamento handle nel metodo delegato URLSession:didCompleteWithError:.
Si consiglia inoltre di gestire i caricamenti che vengono completati mentre l'app è in background.
- Implementare application:handleEventsForBackgroundURLSession:completionHandler in AppDelegate.
- Creare un NSURLSession con l'identificatore fornito.
- Rispondere ai metodi delegato come per il caricamento di solito (ad esempio gestire la risposta in URLSession:didCompleteWithError:)
- chiamata URLSessionDidFinishEventsForBackgroundURLSession dopo aver completato l'elaborazione dell'evento.
Per semplificare la gestione, creare un'attività NSURLSession
per caricamento, ciascuna con un identificativo univoco.
Fare riferimento a URL Session Programming Guide per i dettagli di implementazione.
Esempio 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.
}
}
caricare più immagini in una singola richiesta, le immagini deve prima essere codificato nel tipo MIME multipart/formdata, come avete fatto. La differenza è che questo intero messaggio MIME deve essere salvato in un singolo file, che è il file che viene caricato sul server.
Ecco un esempio che mostra come eseguire questa operazione. Funziona serializzando le parti MIME direttamente su un file. È anche possibile creare il messaggio in un NSData, sebbene si rischi di incorrere in limiti di memoria quando si gestiscono file di grandi dimensioni.
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)
}
ma ho molti dati di modulo immagine, come gestirlo? –
Si prega di aggiornare la domanda per chiarire cosa si sta tentando di fare. Come è attualmente, la tua domanda non menziona nulla su più immagini. –
Dai un'occhiata a [questo tutorial] (http://www.kaleidosblog.com/how-to-upload-images-using-swift-2-send-multipart-post-request), che mostra come usare la codifica MIME per codificare più immagini in una singola richiesta di caricamento. –