美文网首页
Alamofire-多表单上传

Alamofire-多表单上传

作者: Code_人生 | 来源:发表于2019-08-26 15:46 被阅读0次

    一、AFN上传文件

        // 1. 使用AFHTTPSessionManager的接口
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        NSDictionary *dic = @{@"businessType":@"dyz",
                              @"fileType":@"image",
                              @"file":@"img.jpeg"
                              };
        [manager POST:@"http://114.215.186.169:9002/api/demo/test/file" parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            // 在这个block中设置需要上传的文件
            NSString *path = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"jpg"];
            // 将本地图片数据拼接到formData中 指定name
            [formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"file" error:nil];
            
            //或者使用这个接口拼接 指定name和filename
            NSData *picdata  =[NSData dataWithContentsOfFile:path];
            [formData appendPartWithFileData:picdata name:@"image" fileName:@"image.jpg" mimeType:@"image/jpeg"];
            
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            NSLog(@"progress --- %@",uploadProgress.localizedDescription);
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"responseObject-------%@", responseObject);
            dispatch_async(dispatch_get_main_queue(), ^{
                
            });
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"Error-------%@", error);
        }];
    

    二、Alamofire-多表单上传

            SessionManager.default
                .upload(multipartFormData: { (mutilPartData) in
                    mutilPartData.append("dyz".data(using: .utf8)!, withName: "name")
                    mutilPartData.append("IMEdyz".data(using: .utf8)!, withName: "username")
                    mutilPartData.append("123456".data(using: .utf8)!, withName: "PASSWORD")
    
                    //mutilPartData.append(data as! Data, withName: "fileName")
                }, to: urlString) { (result) in
                    print(result)
                    switch result {
                    case .failure(let error):
                        print(error)
                    case .success(let upload,_,_):
                        upload.response(completionHandler: { (response) in
                            print("****:\(response) ****")
                        })
                    }
            }
    
    • 点击.upload
        open func upload(
            multipartFormData: @escaping (MultipartFormData) -> Void,
            usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
            to url: URLConvertible,
            method: HTTPMethod = .post,
            headers: HTTPHeaders? = nil,
            queue: DispatchQueue? = nil,
            encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
        {
            do {
                let urlRequest = try URLRequest(url: url, method: method, headers: headers)
    
                return upload(
                    multipartFormData: multipartFormData,
                    usingThreshold: encodingMemoryThreshold,
                    with: urlRequest,
                    queue: queue,
                    encodingCompletion: encodingCompletion
                )
            } catch {
                (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
            }
        }
    
    • multipartFormData(formData) 执行外部闭包
        open func upload(
            multipartFormData: @escaping (MultipartFormData) -> Void,
            usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
            with urlRequest: URLRequestConvertible,
            queue: DispatchQueue? = nil,
            encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
        {
            DispatchQueue.global(qos: .utility).async {
                let formData = MultipartFormData()
                multipartFormData(formData)
    
                var tempFileURL: URL?
    
                do {
                    var urlRequestWithContentType = try urlRequest.asURLRequest()
                    urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
    
                    let isBackgroundSession = self.session.configuration.identifier != nil
    
                    if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
                        let data = try formData.encode()
    
                        let encodingResult = MultipartFormDataEncodingResult.success(
                            request: self.upload(data, with: urlRequestWithContentType),
                            streamingFromDisk: false,
                            streamFileURL: nil
                        )
    
                        (queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) }
                    } else {
                        let fileManager = FileManager.default
                        let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
                        let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
                        let fileName = UUID().uuidString
                        let fileURL = directoryURL.appendingPathComponent(fileName)
    
                        tempFileURL = fileURL
    
                        var directoryError: Error?
    
                        // Create directory inside serial queue to ensure two threads don't do this in parallel
                        self.queue.sync {
                            do {
                                try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
                            } catch {
                                directoryError = error
                            }
                        }
    
                        if let directoryError = directoryError { throw directoryError }
    
                        try formData.writeEncodedData(to: fileURL)
    
                        let upload = self.upload(fileURL, with: urlRequestWithContentType)
    
                        // Cleanup the temp file once the upload is complete
                        upload.delegate.queue.addOperation {
                            do {
                                try FileManager.default.removeItem(at: fileURL)
                            } catch {
                                // No-op
                            }
                        }
    
                        (queue ?? DispatchQueue.main).async {
                            let encodingResult = MultipartFormDataEncodingResult.success(
                                request: upload,
                                streamingFromDisk: true,
                                streamFileURL: fileURL
                            )
    
                            encodingCompletion?(encodingResult)
                        }
                    }
                } catch {
                    // Cleanup the temp file in the event that the multipart form data encoding failed
                    if let tempFileURL = tempFileURL {
                        do {
                            try FileManager.default.removeItem(at: tempFileURL)
                        } catch {
                            // No-op
                        }
                    }
    
                    (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
                }
            }
        }
    
    • 点击self.upload(data, with: urlRequestWithContentType)
        @discardableResult
        open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
            do {
                let urlRequest = try urlRequest.asURLRequest()
                return upload(.data(data, urlRequest))
            } catch {
                return upload(nil, failedWith: error)
            }
        }
    
    • 点击upload(.data(data, urlRequest))
        private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest {
            do {
                let task = try uploadable.task(session: session, adapter: adapter, queue: queue)
                let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task))
    
                if case let .stream(inputStream, _) = uploadable {
                    upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream }
                }
    
                delegate[task] = upload
    
                if startRequestsImmediately { upload.resume() }
    
                return upload
            } catch {
                return upload(uploadable, failedWith: error)
            }
        }
    

    三、Alamofire-参数的拼接

    • 点击 let formData = MultipartFormData() multipartFormData(formData)MultipartFormData()
      • 1:EncodingCharacters
      • 2:randomBoundary 分三种情况
      • 3:闭包调用
      • 4:contentHeaders + stream + length
      • 5:BodyPart
      • 6:bodyParts add 容器收集
        struct EncodingCharacters {
            static let crlf = "\r\n"
        }
    
        struct BoundaryGenerator {
            enum BoundaryType {
                case initial, encapsulated, final
            }
    
            static func randomBoundary() -> String {
                return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
            }
    
            static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
                let boundaryText: String
    
                switch boundaryType {
                case .initial:
                    boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
                case .encapsulated:
                    boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
                case .final:
                    boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
                }
    
                return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
            }
        }
    
    • 点击let data = try formData.encode()
      • 整体数据 encode - data - request - session
        public func encode() throws -> Data {
            if let bodyPartError = bodyPartError {
                throw bodyPartError
            }
    
            var encoded = Data()
    
            bodyParts.first?.hasInitialBoundary = true
            bodyParts.last?.hasFinalBoundary = true
    
            for bodyPart in bodyParts {
                let encodedData = try encode(bodyPart)
                encoded.append(encodedData)
            }
    
            return encoded
        }
    
        private func encode(_ bodyPart: BodyPart) throws -> Data {
            var encoded = Data()
    
            let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
            encoded.append(initialData)
    
            let headerData = encodeHeaders(for: bodyPart)
            encoded.append(headerData)
    
            let bodyStreamData = try encodeBodyStream(for: bodyPart)
            encoded.append(bodyStreamData)
    
            if bodyPart.hasFinalBoundary {
                encoded.append(finalBoundaryData())
            }
    
            return encoded
        }
    

    相关文章

      网友评论

          本文标题:Alamofire-多表单上传

          本文链接:https://www.haomeiwen.com/subject/henrectx.html