0001    // Upload.swift
0002    //
0003    // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
0004    //
0005    // Permission is hereby granted, free of charge, to any person obtaining a copy
0006    // of this software and associated documentation files (the "Software"), to deal
0007    // in the Software without restriction, including without limitation the rights
0008    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0009    // copies of the Software, and to permit persons to whom the Software is
0010    // furnished to do so, subject to the following conditions:
0011    //
0012    // The above copyright notice and this permission notice shall be included in
0013    // all copies or substantial portions of the Software.
0014    //
0015    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0018    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0020    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
0021    // THE SOFTWARE.
0022    
0023    import Foundation
0024    
0025    extension Manager {
0026        private enum Uploadable
Upload.swift:32
    private func upload(uploadable: Uploadable) -> Request {
{ 0027 case Data
Upload.swift:37
        case .Data(let request, let data):
Upload.swift:122
        return upload(.Data(URLRequest.URLRequest, data))
(NSURLRequest, NSData) 0028 case File
Upload.swift:41
        case .File(let request, let fileURL):
Upload.swift:83
        return upload(.File(URLRequest.URLRequest, file))
(NSURLRequest, NSURL) 0029 case Stream
Upload.swift:45
        case .Stream(let request, let stream):
Upload.swift:162
        return upload(.Stream(URLRequest.URLRequest, stream))
(NSURLRequest, NSInputStream) 0030 } 0031 0032 private func upload
Upload.swift:83
        return upload(.File(URLRequest.URLRequest, file))
Upload.swift:122
        return upload(.Data(URLRequest.URLRequest, data))
Upload.swift:162
        return upload(.Stream(URLRequest.URLRequest, stream))
(uploadable: Uploadable) -> Request { 0033 var uploadTask: NSURLSessionUploadTask! 0034 var HTTPBodyStream: NSInputStream? 0035 0036 switch uploadable { 0037 case .Data(let request, let data): 0038 dispatch_sync(queue) { 0039 uploadTask = self.session.uploadTaskWithRequest(request, fromData: data) 0040 } 0041 case .File(let request, let fileURL): 0042 dispatch_sync(queue) { 0043 uploadTask = self.session.uploadTaskWithRequest(request, fromFile: fileURL) 0044 } 0045 case .Stream(let request, let stream): 0046 dispatch_sync(queue) { 0047 uploadTask = self.session.uploadTaskWithStreamedRequest(request) 0048 } 0049 0050 HTTPBodyStream = stream 0051 } 0052 0053 let request = Request(session: session, task: uploadTask) 0054 0055 if HTTPBodyStream != nil { 0056 request.delegate.taskNeedNewBodyStream = { _, _ in 0057 return HTTPBodyStream 0058 } 0059 } 0060 0061 delegate[request.delegate.task] = request.delegate 0062 0063 if startRequestsImmediately { 0064 request.resume() 0065 } 0066 0067 return request 0068 } 0069 0070 // MARK: File 0071 0072 /** 0073 Creates a request for uploading a file to the specified URL request. 0074 0075 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0076 0077 - parameter URLRequest: The URL request 0078 - parameter file: The file to upload 0079 0080 - returns: The created upload request. 0081 */ 0082 public func upload
Alamofire.swift:181
    return Manager.sharedInstance.upload(URLRequest, file: file)
Upload.swift:106
        return upload(mutableURLRequest, file: file)
Upload.swift:321
                            request: self.upload(URLRequestWithContentType, file: fileURL),
(URLRequest: URLRequestConvertible, file: NSURL) -> Request { 0083 return upload(.File(URLRequest.URLRequest, file)) 0084 } 0085 0086 /** 0087 Creates a request for uploading a file to the specified URL request. 0088 0089 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0090 0091 - parameter method: The HTTP method. 0092 - parameter URLString: The URL string. 0093 - parameter headers: The HTTP headers. `nil` by default. 0094 - parameter file: The file to upload 0095 0096 - returns: The created upload request. 0097 */ 0098 public func upload
Alamofire.swift:169
    return Manager.sharedInstance.upload(method, URLString, headers: headers, file: file)
( 0099 method: Method, 0100 _ URLString: URLStringConvertible, 0101 headers: [String: String]? = nil, 0102 file: NSURL) 0103 -> Request 0104 { 0105 let mutableURLRequest = URLRequest(method, URLString, headers: headers) 0106 return upload(mutableURLRequest, file: file) 0107 } 0108 0109 // MARK: Data 0110 0111 /** 0112 Creates a request for uploading data to the specified URL request. 0113 0114 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0115 0116 - parameter URLRequest: The URL request. 0117 - parameter data: The data to upload. 0118 0119 - returns: The created upload request. 0120 */ 0121 public func upload
Alamofire.swift:215
    return Manager.sharedInstance.upload(URLRequest, data: data)
Upload.swift:146
        return upload(mutableURLRequest, data: data)
Upload.swift:295
                        request: self.upload(URLRequestWithContentType, data: data),
(URLRequest: URLRequestConvertible, data: NSData) -> Request { 0122 return upload(.Data(URLRequest.URLRequest, data)) 0123 } 0124 0125 /** 0126 Creates a request for uploading data to the specified URL request. 0127 0128 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0129 0130 - parameter method: The HTTP method. 0131 - parameter URLString: The URL string. 0132 - parameter headers: The HTTP headers. `nil` by default. 0133 - parameter data: The data to upload 0134 0135 - returns: The created upload request. 0136 */ 0137 public func upload
Alamofire.swift:203
    return Manager.sharedInstance.upload(method, URLString, headers: headers, data: data)
( 0138 method: Method, 0139 _ URLString: URLStringConvertible, 0140 headers: [String: String]? = nil, 0141 data: NSData) 0142 -> Request 0143 { 0144 let mutableURLRequest = URLRequest(method, URLString, headers: headers) 0145 0146 return upload(mutableURLRequest, data: data) 0147 } 0148 0149 // MARK: Stream 0150 0151 /** 0152 Creates a request for uploading a stream to the specified URL request. 0153 0154 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0155 0156 - parameter URLRequest: The URL request. 0157 - parameter stream: The stream to upload. 0158 0159 - returns: The created upload request. 0160 */ 0161 public func upload
Alamofire.swift:249
    return Manager.sharedInstance.upload(URLRequest, stream: stream)
Upload.swift:186
        return upload(mutableURLRequest, stream: stream)
(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request { 0162 return upload(.Stream(URLRequest.URLRequest, stream)) 0163 } 0164 0165 /** 0166 Creates a request for uploading a stream to the specified URL request. 0167 0168 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0169 0170 - parameter method: The HTTP method. 0171 - parameter URLString: The URL string. 0172 - parameter headers: The HTTP headers. `nil` by default. 0173 - parameter stream: The stream to upload. 0174 0175 - returns: The created upload request. 0176 */ 0177 public func upload
Alamofire.swift:237
    return Manager.sharedInstance.upload(method, URLString, headers: headers, stream: stream)
( 0178 method: Method, 0179 _ URLString: URLStringConvertible, 0180 headers: [String: String]? = nil, 0181 stream: NSInputStream) 0182 -> Request 0183 { 0184 let mutableURLRequest = URLRequest(method, URLString, headers: headers) 0185 0186 return upload(mutableURLRequest, stream: stream) 0187 } 0188 0189 // MARK: MultipartFormData 0190 0191 /// Default memory threshold used when encoding `MultipartFormData`. 0192 public static let MultipartFormDataEncodingMemoryThreshold
Alamofire.swift:270
    encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
Alamofire.swift:295
    encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
Upload.swift:239
        encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
Upload.swift:279
        encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
: UInt64 = 10 * 1024 * 1024 0193 0194 /** 0195 Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as 0196 associated values. 0197 0198 - Success: Represents a successful `MultipartFormData` encoding and contains the new `Request` along with 0199 streaming information. 0200 - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding 0201 error. 0202 */ 0203 public enum MultipartFormDataEncodingResult
Alamofire.swift:271
    encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
Alamofire.swift:296
    encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
Upload.swift:240
        encodingCompletion: (MultipartFormDataEncodingResult -> Void)?)
Upload.swift:280
        encodingCompletion: (MultipartFormDataEncodingResult -> Void)?)
Upload.swift:294
                    let encodingResult = MultipartFormDataEncodingResult.Success(
Upload.swift:320
                        let encodingResult = MultipartFormDataEncodingResult.Success(
{ 0204 case Success
Upload.swift:294
                    let encodingResult = MultipartFormDataEncodingResult.Success(
Upload.swift:320
                        let encodingResult = MultipartFormDataEncodingResult.Success(
(request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) 0205 case Failure
Upload.swift:305
                        encodingCompletion?(.Failure(error as NSError))
Upload.swift:329
                        encodingCompletion?(.Failure(error as NSError))
(ErrorType) 0206 } 0207 0208 /** 0209 Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 0210 0211 It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 0212 payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 0213 efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 0214 be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 0215 footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 0216 used for larger payloads such as video content. 0217 0218 The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 0219 or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 0220 encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 0221 during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 0222 technique was used. 0223 0224 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0225 0226 - parameter method: The HTTP method. 0227 - parameter URLString: The URL string. 0228 - parameter headers: The HTTP headers. `nil` by default. 0229 - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 0230 - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 0231 `MultipartFormDataEncodingMemoryThreshold` by default. 0232 - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 0233 */ 0234 public func upload
Alamofire.swift:273
    return Manager.sharedInstance.upload(
( 0235 method: Method, 0236 _ URLString: URLStringConvertible, 0237 headers: [String: String]? = nil, 0238 multipartFormData: MultipartFormData -> Void, 0239 encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 0240 encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 0241 { 0242 let mutableURLRequest = URLRequest(method, URLString, headers: headers) 0243 0244 return upload( 0245 mutableURLRequest, 0246 multipartFormData: multipartFormData, 0247 encodingMemoryThreshold: encodingMemoryThreshold, 0248 encodingCompletion: encodingCompletion 0249 ) 0250 } 0251 0252 /** 0253 Encodes the `MultipartFormData` and creates a request to upload the result to the specified URL request. 0254 0255 It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative 0256 payload is small, encoding the data in-memory and directly uploading to a server is the by far the most 0257 efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to 0258 be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory 0259 footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be 0260 used for larger payloads such as video content. 0261 0262 The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory 0263 or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, 0264 encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk 0265 during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding 0266 technique was used. 0267 0268 If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. 0269 0270 - parameter URLRequest: The URL request. 0271 - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. 0272 - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. 0273 `MultipartFormDataEncodingMemoryThreshold` by default. 0274 - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. 0275 */ 0276 public func upload
Alamofire.swift:298
    return Manager.sharedInstance.upload(
Upload.swift:244
        return upload(
( 0277 URLRequest: URLRequestConvertible, 0278 multipartFormData: MultipartFormData -> Void, 0279 encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold, 0280 encodingCompletion: (MultipartFormDataEncodingResult -> Void)?) 0281 { 0282 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 0283 let formData = MultipartFormData() 0284 multipartFormData(formData) 0285 0286 let URLRequestWithContentType = URLRequest.URLRequest 0287 URLRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type") 0288 0289 let isBackgroundSession = self.session.configuration.identifier != nil 0290 0291 if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession { 0292 do { 0293 let data = try formData.encode() 0294 let encodingResult = MultipartFormDataEncodingResult.Success( 0295 request: self.upload(URLRequestWithContentType, data: data), 0296 streamingFromDisk: false, 0297 streamFileURL: nil 0298 ) 0299 0300 dispatch_async(dispatch_get_main_queue()) { 0301 encodingCompletion?(encodingResult) 0302 } 0303 } catch { 0304 dispatch_async(dispatch_get_main_queue()) { 0305 encodingCompletion?(.Failure(error as NSError)) 0306 } 0307 } 0308 } else { 0309 let fileManager = NSFileManager.defaultManager() 0310 let tempDirectoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) 0311 let directoryURL = tempDirectoryURL.URLByAppendingPathComponent("com.alamofire.manager/multipart.form.data") 0312 let fileName = NSUUID().UUIDString 0313 let fileURL = directoryURL.URLByAppendingPathComponent(fileName) 0314 0315 do { 0316 try fileManager.createDirectoryAtURL(directoryURL, withIntermediateDirectories: true, attributes: nil) 0317 try formData.writeEncodedDataToDisk(fileURL) 0318 0319 dispatch_async(dispatch_get_main_queue()) { 0320 let encodingResult = MultipartFormDataEncodingResult.Success( 0321 request: self.upload(URLRequestWithContentType, file: fileURL), 0322 streamingFromDisk: true, 0323 streamFileURL: fileURL 0324 ) 0325 encodingCompletion?(encodingResult) 0326 } 0327 } catch { 0328 dispatch_async(dispatch_get_main_queue()) { 0329 encodingCompletion?(.Failure(error as NSError)) 0330 } 0331 } 0332 } 0333 } 0334 } 0335 } 0336 0337 // MARK: - 0338 0339 extension Request { 0340 0341 // MARK: - UploadTaskDelegate 0342 0343 class UploadTaskDelegate
Manager.swift:430
            } else if let delegate = self[task] as? Request.UploadTaskDelegate {
Request.swift:61
            delegate = UploadTaskDelegate(task: task)
Request.swift:124
        if let uploadDelegate = delegate as? UploadTaskDelegate {
: DataTaskDelegate { 0344 var uploadTask: NSURLSessionUploadTask? { return task as? NSURLSessionUploadTask } 0345 var uploadProgress
Request.swift:125
            uploadDelegate.uploadProgress = closure
Upload.swift:370
                uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend)
: ((Int64, Int64, Int64) -> Void)! 0346 0347 // MARK: - NSURLSessionTaskDelegate 0348 0349 // MARK: Override Closures 0350 0351 var taskDidSendBodyData
Upload.swift:364
            if let taskDidSendBodyData = taskDidSendBodyData {
: ((NSURLSession, NSURLSessionTask, Int64, Int64, Int64) -> Void)? 0352 0353 // MARK: Delegate Methods 0354 0355 func URLSession
Manager.swift:431
                delegate.URLSession(
( 0356 session: NSURLSession, 0357 task: NSURLSessionTask, 0358 didSendBodyData bytesSent: Int64, 0359 totalBytesSent: Int64, 0360 totalBytesExpectedToSend: Int64) 0361 { 0362 if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 0363 0364 if let taskDidSendBodyData = taskDidSendBodyData { 0365 taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) 0366 } else { 0367 progress.totalUnitCount = totalBytesExpectedToSend 0368 progress.completedUnitCount = totalBytesSent 0369 0370 uploadProgress?(bytesSent, totalBytesSent, totalBytesExpectedToSend) 0371 } 0372 } 0373 } 0374 } 0375