使用swift中的session.uploadTask上传失败如何检查错误?
How to check error if uploading is failed using session.uploadTask in swift?
我正在后台上传视频文件,但我不知道如何检查视频文件是否上传失败。我正在使用 URLSession 上传文件。如果有人有想法请帮助我。
private func uploadMediaWith(mediaURL: URL, mediaMimeType: MediaMimeType, AWSPresignedURL: URL) {
let finalMediaURL = mediaURL.updatedSandboxURL()
Log.echo(key: "\(self.KEY)", text: "setup upload for \(mediaURL.lastPathComponent)")
let url = AWSPresignedURL // https://dentiscope-development.s3.us-west-2.amazonaws.com/exams/42/videos/BottomLeftOutside-b121986d-bd5c-4b6f-bed2-f030978f03f0.mp4?x-amz-acl=private&x-amz-meta-exam_id=42&x-amz-meta-uuid=b121986d-bd5c-4b6f-bed2-f030978f03f0&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5WF3XEUH4WAYWLEI%2F20211115%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20211115T070402Z&X-Amz-SignedHeaders=host%3Bx-amz-acl%3Bx-amz-meta-exam_id%3Bx-amz-meta-uuid&X-Amz-Expires=432000&X-Amz-Signature=a6ede8cd558cd1df5c5d6e62be1237f995b7ac97e235112acc263e3b0de1531f
let boundary = UUID().uuidString
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
if let authToken = SignedUserInfo.sharedInstance?.authToken {
request.setValue("Authorization", forHTTPHeaderField: "Bearer " + authToken)
}
let config = URLSessionConfiguration.background(withIdentifier: boundary)
config.waitsForConnectivity = true
config.shouldUseExtendedBackgroundIdleMode = true
// config.httpMaximumConnectionsPerHost = 4
// config.networkServiceType = .background
let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
var data = Data()
if(mediaMimeType == MediaMimeType.video) {
do {
let videoData = try Data(contentsOf: finalMediaURL)
data.append(videoData)
} catch {
Log.echo(key: "MediaMimeType.video", text: error.localizedDescription)
fatalError("\(self.KEY) COULD NOT GET DATA OF THE VIDEO || \(finalMediaURL.lastPathComponent)")
}
}
request.httpBody = data
DispatchQueue.global().async {
let task = session.uploadTask(withStreamedRequest: request)
// how to check if failled to uload
self.uploadingURL = finalMediaURL
task.resume()
Log.echo(key: "\(self.KEY)", text: "execute upload for \(mediaURL.lastPathComponent) || session id \(boundary)")
}
}
如果我使用此代码:
let task = session.dataTask(with: request) { (data, urlResp, error) in
if let error = error {
print(error)
}
} //uploadTask(withStreamedRequest: request)
self.uploadingURL = finalMediaURL
task.resume()
然后出现此错误:
由于未捕获的异常 'NSGenericException' 而终止应用程序,原因:'Completion handler blocks are not supported in background sessions. Use a delegate instead.'
以 NSException
类型的未捕获异常终止
使用委托并将其转换为完成块,您可以使用如下内容:
class UploadContainer: NSObject, URLSessionTaskDelegate {
let session: URLSession
let request: URLRequest
private var completion: ((_ error: Error?) -> Void)?
private var task: URLSessionUploadTask?
private var selfRetain: Any? // This is to persist lifetime of this class for the duration of request execution
init(request: URLRequest, session: URLSession = .shared, completion: @escaping ((_ error: Error?) -> Void)) {
self.request = request
self.session = session
self.completion = completion
super.init()
self.upload()
}
private func upload() {
let task = session.uploadTask(withStreamedRequest: self.request)
self.task = task
task.delegate = self
self.selfRetain = self
task.resume()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
self.selfRetain = nil
completion?(error)
completion = nil
}
}
然后当您生成请求时,您只需调用
UploadContainer(request: request) { error in
if let error = error {
print("Error occurred uploading file \(error)")
} else {
print("File was successfully uploaded")
}
}
但是有很多方法可以实现这一点。重点是一旦你创建了一个任务,你需要分配一个委托。在提供的代码中,您可以看到这一行 task.delegate = self
。无论谁被指定为委托人(在本例中 self
为 UploadContainer
)都需要实现由 : NSObject, URLSessionTaskDelegate
完成的委托。 class 现在可以实现 URLSessionTaskDelegate
中记录的一些方法。但是我们只对完成上传感兴趣(有或没有错误)这似乎是一种名为func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
的方法。我希望这对你有用。
我正在后台上传视频文件,但我不知道如何检查视频文件是否上传失败。我正在使用 URLSession 上传文件。如果有人有想法请帮助我。
private func uploadMediaWith(mediaURL: URL, mediaMimeType: MediaMimeType, AWSPresignedURL: URL) {
let finalMediaURL = mediaURL.updatedSandboxURL()
Log.echo(key: "\(self.KEY)", text: "setup upload for \(mediaURL.lastPathComponent)")
let url = AWSPresignedURL // https://dentiscope-development.s3.us-west-2.amazonaws.com/exams/42/videos/BottomLeftOutside-b121986d-bd5c-4b6f-bed2-f030978f03f0.mp4?x-amz-acl=private&x-amz-meta-exam_id=42&x-amz-meta-uuid=b121986d-bd5c-4b6f-bed2-f030978f03f0&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5WF3XEUH4WAYWLEI%2F20211115%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20211115T070402Z&X-Amz-SignedHeaders=host%3Bx-amz-acl%3Bx-amz-meta-exam_id%3Bx-amz-meta-uuid&X-Amz-Expires=432000&X-Amz-Signature=a6ede8cd558cd1df5c5d6e62be1237f995b7ac97e235112acc263e3b0de1531f
let boundary = UUID().uuidString
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
if let authToken = SignedUserInfo.sharedInstance?.authToken {
request.setValue("Authorization", forHTTPHeaderField: "Bearer " + authToken)
}
let config = URLSessionConfiguration.background(withIdentifier: boundary)
config.waitsForConnectivity = true
config.shouldUseExtendedBackgroundIdleMode = true
// config.httpMaximumConnectionsPerHost = 4
// config.networkServiceType = .background
let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
var data = Data()
if(mediaMimeType == MediaMimeType.video) {
do {
let videoData = try Data(contentsOf: finalMediaURL)
data.append(videoData)
} catch {
Log.echo(key: "MediaMimeType.video", text: error.localizedDescription)
fatalError("\(self.KEY) COULD NOT GET DATA OF THE VIDEO || \(finalMediaURL.lastPathComponent)")
}
}
request.httpBody = data
DispatchQueue.global().async {
let task = session.uploadTask(withStreamedRequest: request)
// how to check if failled to uload
self.uploadingURL = finalMediaURL
task.resume()
Log.echo(key: "\(self.KEY)", text: "execute upload for \(mediaURL.lastPathComponent) || session id \(boundary)")
}
}
如果我使用此代码:
let task = session.dataTask(with: request) { (data, urlResp, error) in
if let error = error {
print(error)
}
} //uploadTask(withStreamedRequest: request)
self.uploadingURL = finalMediaURL
task.resume()
然后出现此错误: 由于未捕获的异常 'NSGenericException' 而终止应用程序,原因:'Completion handler blocks are not supported in background sessions. Use a delegate instead.' 以 NSException
类型的未捕获异常终止使用委托并将其转换为完成块,您可以使用如下内容:
class UploadContainer: NSObject, URLSessionTaskDelegate {
let session: URLSession
let request: URLRequest
private var completion: ((_ error: Error?) -> Void)?
private var task: URLSessionUploadTask?
private var selfRetain: Any? // This is to persist lifetime of this class for the duration of request execution
init(request: URLRequest, session: URLSession = .shared, completion: @escaping ((_ error: Error?) -> Void)) {
self.request = request
self.session = session
self.completion = completion
super.init()
self.upload()
}
private func upload() {
let task = session.uploadTask(withStreamedRequest: self.request)
self.task = task
task.delegate = self
self.selfRetain = self
task.resume()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
self.selfRetain = nil
completion?(error)
completion = nil
}
}
然后当您生成请求时,您只需调用
UploadContainer(request: request) { error in
if let error = error {
print("Error occurred uploading file \(error)")
} else {
print("File was successfully uploaded")
}
}
但是有很多方法可以实现这一点。重点是一旦你创建了一个任务,你需要分配一个委托。在提供的代码中,您可以看到这一行 task.delegate = self
。无论谁被指定为委托人(在本例中 self
为 UploadContainer
)都需要实现由 : NSObject, URLSessionTaskDelegate
完成的委托。 class 现在可以实现 URLSessionTaskDelegate
中记录的一些方法。但是我们只对完成上传感兴趣(有或没有错误)这似乎是一种名为func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
的方法。我希望这对你有用。