Alamofire-多表单处理
HTTP请求实质上是对指定数据格式的拼接,然后将拼接后的数据进行传输。下面对多表单数据处理进行分析。
主要完成以下工作:
- 拼接整合原始数据
- encode为stream流
- upload网络处理:request-task-resume
首先看应用实例:
func alamofireUploadFile(){
let data = self.readLocalData(fileNameStr: "Cooci", type: "jpg")
SessionManager.default
.upload(multipartFormData: { (mutilPartData) in
mutilPartData.append("Apple".data(using: .utf8)!, withName: "name")
mutilPartData.append("Banana".data(using: .utf8)!, withName: "username")
mutilPartData.append("Orange".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,
with urlRequest: URLRequestConvertible,
queue: DispatchQueue? = nil,
encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
{
DispatchQueue.global(qos: .utility).async {
let formData = MultipartFormData()
multipartFormData(formData)
...
}
MultipartFormData类
嵌套结构体类,用于存储信息。主要进行设置boundary分隔符、
EncodingCharacters设置“\r\n”符号、randomBoundary设置随机boundary、设置boundaryData等一系列操作。
append函数
public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
bodyParts.append(bodyPart)
}
构造BodyPart对象,并添加到bodyParts容器中。
BodyPart类
class BodyPart {
let headers: HTTPHeaders
let bodyStream: InputStream
let bodyContentLength: UInt64
var hasInitialBoundary = false
var hasFinalBoundary = false
init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
self.headers = headers
self.bodyStream = bodyStream
self.bodyContentLength = bodyContentLength
}
}
使用面向对象的设计模式,将contentHeaders + stream + length 封装为对象BodyPart,然后放到bodyParts容器中:bodyParts.append(bodyPart)。
bodyParts中数据的使用
我们回到upload函数:这里采用异步async调用进行处理,do循环中对bodyParts数据进行使用。
encode()函数
将bodyParts容器中的数据拼接到一起并返回。
upload:最终网络请求上传函数
这就回到了我们熟悉的SessionManager中的upload函数了。由于前面文章已经对upload进行了阐述,此处不再赘述。
注:为什么数据要拼接为stream进行传输呢?
Stream流传输能够减轻系统压力,节省内存。
多表单上传总结:bodyParts整合数据 -> encode为stream流数据 -> request请求 -> upload网络请求。