Alamofire-表單上傳

本文探索一下Alamofire多表單上傳的實(shí)現(xiàn)

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. 拼接一個(gè)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做了什么數(shù)據(jù)處理
如果formData.contentLength < encodingMemoryThreshold && !isBackgroundSession則是內(nèi)存數(shù)據(jù)上傳

一:內(nèi)存數(shù)據(jù)上傳

  1. 設(shè)置Content-Type
urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
  1. formData數(shù)據(jù)處理
 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
    }

這里是對(duì)bodyParts里的模型數(shù)據(jù)進(jìn)行處理,最后拼接成Data數(shù)據(jù),作為httpBody數(shù)據(jù)上傳,其中需要注意點(diǎn)是bodyPart.bodyStream,是以流數(shù)據(jù)的形式上傳,避免內(nèi)存過(guò)高問(wèn)題。具體代碼不在上傳

  1. 生成MultipartFormDataEncodingResult 枚舉對(duì)象,upload開(kāi)始上傳數(shù)據(jù)
  let encodingResult = MultipartFormDataEncodingResult.success(
                        request: self.upload(data, with: urlRequestWithContentType),
                        streamingFromDisk: false,
                        streamFileURL: nil
                    )

生成UploadRequest,開(kāi)始上傳數(shù)據(jù)

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. 主線程異步回調(diào)上傳結(jié)果
(queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容