我想上传一个图像文件到后端服务器,使用特定的URL端点。我可以很容易地使用Alamofire的上传请求作为multipartFormData。但是,我想摆脱Alamofire,以最大限度地减少对第三方框架的依赖。以下是Alamofire代码,它的工作:
func uploadRequestAlamofire(parameters: [String: Any], imageData: Data?, completion: @escaping(CustomError?) -> Void ) {
let url = imageUploadEndpoint!
let headers: HTTPHeaders = ["X-User-Agent": "ios",
"Accept-Language": "en",
"Accept": "application/json",
"Content-type": "multipart/form-data",
"ApiKey": KeychainService.getString(by: KeychainKey.apiKey) ?? ""]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = imageData {
multipartFormData.append(data, withName: "file", fileName: "image.png", mimeType: "image/jpg")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
completion(CustomError(errorCode: response.response!.statusCode))
print("Succesfully uploaded")
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
}
}
以下是URLSession上载任务,该任务不起作用:
func requestNativeImageUpload(imageData: Data, orderExtId: String) {
var request = URLRequest(url: imageUploadEndpoint!)
request.httpMethod = "POST"
request.timeoutInterval = 10
request.allHTTPHeaderFields = [
"X-User-Agent": "ios",
"Accept-Language": "en",
"Accept": "application/json",
"Content-type": "multipart/form-data",
"ApiKey": KeychainService.getString(by: KeychainKey.apiKey) ?? ""
]
let body = OrderUpload(order_ext_id: orderExtId, file: imageData)
do {
request.httpBody = try encoder.encode(body)
} catch let error {
print(error.localizedDescription)
}
let session = URLSession.shared
session.uploadTask(with: request, from: imageData) { data, response, error in
guard let response = response as? HTTPURLResponse else { return }
print(response)
if error != nil {
print(error!.localizedDescription)
}
}.resume()
}
这是我调用Alamofire和URLSession方法的方式:
uploadRequestAlamofire(parameters: ["order_ext_id": order_ext_id, "file": "image.jpg"], imageData: uploadImage) { [weak self] response in }
requestNativeImageUpload(imageData: uploadImage!, orderExtId: order_ext_id)
以下是后端服务器期望在请求正文中接收的内容:
let order_ext_id: String
let description: String
let file: string($binary)
这是要为请求的httpBody编码的可编码结构。
struct OrderUpload: Codable {
let order_ext_id: String
let description: String
let file: String
}
虽然在这个演示中我的方法可能不完全合适,并且我不处理响应状态代码,但是Alamofire方法工作得很好。
为什么URLSession不能工作?
3条答案
按热度按时间mo49yndu1#
最后我终于找到了解决办法。来源是:URLSession: Multipart Form-Data Requests | Swift 3, Xcode 8。在我的特定情况下,我需要提供orderExtId作为后端服务器接受我的映像的参数。您的情况可能会有所不同,这取决于后端的要求。
pes8fvy92#
1.标头中的Content-Type错误。它应如下所示:
1.您需要基于对象中的每个字段形成主体,就像您在Alamofire示例中向multipartFormData添加值一样(您在那里使用了字典)
向数据添加字符串的助手:
bkkx9g8r3#
这是一个多部分的编码器,Custom Swift Encoder/Decoder for the Strings Resource Format,你可以直接转换成多部分的表单数据。把编码后的数据附加到你的主体数据上。
用法: