【发布时间】:2023-03-09 23:06:01
【问题描述】:
我正在通过Alamofire.upload 在服务器上上传图像作为多部分数据。与Alamofire.request 不同,它不返回Request 对象,我通常用它来取消请求。
但是像上传这样的消费请求能够取消是很合理的。在 Alamofire 中有哪些选项?
【问题讨论】:
我正在通过Alamofire.upload 在服务器上上传图像作为多部分数据。与Alamofire.request 不同,它不返回Request 对象,我通常用它来取消请求。
但是像上传这样的消费请求能够取消是很合理的。在 Alamofire 中有哪些选项?
【问题讨论】:
在我的例子中,我在我的 API 类中创建了“sessionManager”实例,并为 Alamofire 的会话管理器分配了配置。
var sessionManager: SessionManager!
// Setup request manager
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = TimeInterval(15.0)
configuration.timeoutIntervalForRequest = TimeInterval(15.0)
sessionManager = Alamofire.SessionManager(configuration: configuration)
sessionManager.upload(multipartFormData: { multipartFormData in
// AppendMultipart parts
multipartFormData.append(metadataBodyPart, withName: PartName.Metadata, mimeType: MimeType.MultiPart)
multipartFormData.append(imageDataBodyPart, withName: PartName.Photo, mimeType: MimeType.ImageJPG)
} // ... rest of the code
然后我可以创建一个方法来取消任何当前的请求类型。请注意,此处“(_,uploadTasks,_)”您还可以拥有“dataTasks”和“downloadTasks”,如果您愿意,也可以取消“(dataTasks,uploadTasks,downloadTasks)”
func cancelUploadRequest() {
sessionManager.session.getTasksWithCompletionHandler { (_, uploadTasks, _) in
uploadTasks.forEach { $0.cancel() }
}
}
你也可以这样:
func cancel(request: CancelRequestType) {
sessionManager.session.getTasksWithCompletionHandler { (dataTasks, uploadTasks, downloadTasks) in
switch request {
case .DataTask:
dataTasks.forEach { $0.cancel() }
print("- - - Data task was canceled!")
case .UploadTask:
uploadTasks.forEach { $0.cancel() }
print("- - - Upload task was canceled!")
case .DownloadTask:
downloadTasks.forEach { $0.cancel() }
print("- - - Download task was canceled!")
case .ZeroTask:
print("- - - Zero tasks was found!")
}
}
}
其中“CancelRequestType”是枚举。所以你可以调用API.cancel(request: .UploadTask)之类的方法
enum CancelRequestType: String {
case DownloadTask = "DownloadTask"
case DataTask = "DataTask"
case UploadTask = "UploadTask"
case ZeroTask = "Zero"
}
【讨论】:
可以准备一个闭包,并将请求从“encodingCompletion”中转移出来
class NetworkManager {
private var closure: ((Request)->())?
func startUpload() {
Alamofire.upload(
.POST,
"https://httpbin.org/post",
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
self.closure?(upload)
upload.responseJSON { response in
debugPrint(response)
uploadRequest = nil
}
case .Failure(let encodingError):
print(encodingError)
}
}
)
}
}
【讨论】:
使用 Alamofire README 中的 Uploading MultiPartFormData 示例:
Alamofire.upload(
.POST,
"https://httpbin.org/post",
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .Failure(let encodingError):
print(encodingError)
}
}
)
在这里,upload.responseJSON 返回一个Request,它应该允许您将其分配给某事以便稍后取消。例如:
let request = upload.responseJSON { ...
...
request.cancel()
【讨论】:
恐怕你不能,根据 Alamofire 源代码,upload 函数在所有支持 MultipartFormData 的重载 except 中返回 Request 类型 见以下代码:
// MARK: MultipartFormData
/**
Creates an upload request using the shared manager instance for the specified method and URL string.
- parameter method: The HTTP method.
- parameter URLString: The URL string.
- parameter headers: The HTTP headers. `nil` by default.
- parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
- parameter encodingMemoryThreshold: The encoding memory threshold in bytes. `MultipartFormDataEncodingMemoryThreshold`
by default.
- parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
*/
public func upload(
method: Method,
URLString: URLStringConvertible,
headers: [String: String]? = nil,
multipartFormData: MultipartFormData -> Void,
encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
{
return Manager.sharedInstance.upload(
method,
URLString,
headers: headers,
multipartFormData: multipartFormData,
encodingMemoryThreshold: encodingMemoryThreshold,
encodingCompletion: encodingCompletion
)
}
/**
Creates an upload request using the shared manager instance for the specified method and URL string.
- parameter URLRequest: The URL request.
- parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
- parameter encodingMemoryThreshold: The encoding memory threshold in bytes. `MultipartFormDataEncodingMemoryThreshold`
by default.
- parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
*/
public func upload(
URLRequest: URLRequestConvertible,
multipartFormData: MultipartFormData -> Void,
encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
{
return Manager.sharedInstance.upload(
URLRequest,
multipartFormData: multipartFormData,
encodingMemoryThreshold: encodingMemoryThreshold,
encodingCompletion: encodingCompletion
)
}
建议您在编写客户端代码时使用multipart/form-data,当您的表单包含任何<input type="file"> 元素时。
因此,如果您只想将图像上传到服务器,您可以使用另一个 upload 函数重载,该函数返回一个 Request 对象,您可以像 Alamofire 文档中建议的那样取消它:
let fileURL = NSBundle.mainBundle().URLForResource("Default", withExtension: "png")
ler request =Alamofire.upload(.POST, "https://httpbin.org/post", file: fileURL)
// request.cancel()
希望对你有所帮助。
【讨论】: