// Alamofire.swift // // Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import Foundation extension Manager { private enum Uploadable { case Data(NSURLRequest, NSData) case File(NSURLRequest, NSURL) case Stream(NSURLRequest, NSInputStream) } private func upload(uploadable: Uploadable) -> Request { var uploadTask: NSURLSessionUploadTask! var HTTPBodyStream: NSInputStream? switch uploadable { case .Data(let request, let data): dispatch_sync(queue) { uploadTask = self.session.uploadTaskWithRequest(request, fromData: data) } case .File(let request, let fileURL): dispatch_sync(queue) { uploadTask = self.session.uploadTaskWithRequest(request, fromFile: fileURL) } case .Stream(let request, var stream): dispatch_sync(queue) { uploadTask = self.session.uploadTaskWithStreamedRequest(request) } HTTPBodyStream = stream } let request = Request(session: session, task: uploadTask) if HTTPBodyStream != nil { request.delegate.taskNeedNewBodyStream = { _, _ in return HTTPBodyStream } } delegate[request.delegate.task] = request.delegate if startRequestsImmediately { request.resume() } return request } // MARK: File /** Creates a request for uploading a file to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: URLRequest The URL request :param: file The file to upload :returns: The created upload request. */ public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request { return upload(.File(URLRequest.URLRequest, file)) } /** Creates a request for uploading a file to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: method The HTTP method. :param: URLString The URL string. :param: file The file to upload :returns: The created upload request. */ public func upload(method: Method, _ URLString: URLStringConvertible, file: NSURL) -> Request { return upload(URLRequest(method, URLString), file: file) } // MARK: Data /** Creates a request for uploading data to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: URLRequest The URL request :param: data The data to upload :returns: The created upload request. */ public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request { return upload(.Data(URLRequest.URLRequest, data)) } /** Creates a request for uploading data to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: method The HTTP method. :param: URLString The URL string. :param: data The data to upload :returns: The created upload request. */ public func upload(method: Method, _ URLString: URLStringConvertible, data: NSData) -> Request { return upload(URLRequest(method, URLString), data: data) } // MARK: Stream /** Creates a request for uploading a stream to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: URLRequest The URL request :param: stream The stream to upload :returns: The created upload request. */ public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { return upload(.Stream(URLRequest.URLRequest, stream)) } /** Creates a request for uploading a stream to the specified URL request. If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. :param: method The HTTP method. :param: URLString The URL string. :param: stream The stream to upload. :returns: The created upload request. */ public func upload(method: Method, _ URLString: URLStringConvertible, stream: NSInputStream) -> Request { return upload(URLRequest(method, URLString), stream: stream) } } // MARK: - extension Request { // MARK: - UploadTaskDelegate class UploadTaskDelegate: DataTaskDelegate { var uploadTask: NSURLSessionUploadTask! { return task as! NSURLSessionUploadTask } var uploadProgress: ((Int64, Int64, Int64) -> Void)! // MARK: - NSURLSessionTaskDelegate func URLSession(session: NSURLSession!, task: NSURLSessionTask!, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { progress.totalUnitCount = totalBytesExpectedToSend progress.completedUnitCount = totalBytesSent uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend) } } }