Alamofire-表单上传

本文探索一下Alamofire多表单上传的实现

SessionManager.default
            .upload(multipartFormData: { (formData) in
                formData.append("lili".data(using: .utf8)!, withName: "name")
                formData.append("22".data(using: .utf8)!, withName: "age")
            }, to: url) { (result) in
                switch result {
                case .failure(let error):
                    print(error)
                case .success(let upload, _, _):
                    upload.response(completionHandler: { (response) in
                        print(response)
                    })
                }
            }

首先看一下formData.append做了什么

  1. 拼接一个header
        var disposition = "form-data; name=\"\(name)\""
        if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
        var headers = ["Content-Disposition": disposition]
        if let mimeType = mimeType { headers["Content-Type"] = mimeType }
        return headers
  1. 处理data
        let stream = InputStream(data: data)
        let length = UInt64(data.count)
        append(stream, withLength: length, headers: headers)
  1. 生成model:BodyPart,保存modelbodyParts
let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
bodyParts.append(bodyPart)

其次,看看upload做了什么数据处理
如果formData.contentLength < encodingMemoryThreshold && !isBackgroundSession则是内存数据上传

一:内存数据上传

  1. 设置Content-Type
urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
  1. formData数据处理
 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
    }

这里是对bodyParts里的模型数据进行处理,最后拼接成Data数据,作为httpBody数据上传,其中需要注意点是bodyPart.bodyStream,是以流数据的形式上传,避免内存过高问题。具体代码不在上传

  1. 生成MultipartFormDataEncodingResult 枚举对象,upload开始上传数据
  let encodingResult = MultipartFormDataEncodingResult.success(
                        request: self.upload(data, with: urlRequestWithContentType),
                        streamingFromDisk: false,
                        streamFileURL: nil
                    )

生成UploadRequest,开始上传数据

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)
        }
    }
  1. 主线程异步回调上传结果
(queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容