【发布时间】:2017-06-28 09:49:54
【问题描述】:
我需要在后台将 mp4 视频文件从 iPhone/iPad 上传到服务器,所以我读到了 URLSession.uploadTask(with: URLRequest, fromFile: URL)方法,但我不明白我之前如何准备请求。我需要创建一个 multipart/form-data 请求,因为我想附加其他字符串参数。
func requestBodyFor(video: URL) -> Data? {
let url = URL(string: "url_of_upload_handler.php")!
let parameters = ["type":"video", "user":"112"]
do {
let kBoundary = "Boundary-\(UUID().uuidString)"
let kStartTag = "--%@\r\n"
let kEndTag = "\r\n"
let kContent = "Content-Disposition: form-data; name=\"%@\"\r\n\r\n"
var body = Data()
let videoData = try Data(contentsOf: video)
// parameters
for (key,value) in parameters {
body.append(String(format: kStartTag, kBoundary).data(using: String.Encoding.utf8)!)
body.append(String(format: kContent, key).data(using: String.Encoding.utf8)!)
body.append(value.data(using: String.Encoding.utf8)!)
body.append(String(format: kEndTag).data(using: String.Encoding.utf8)!)
}
//Video data
body.append(String(format: kStartTag, boundary).data(using: String.Encoding.utf8)!)
body.append(String(format: "Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", "file", video.lastPathComponent).data(using: String.Encoding.utf8)!)
body.append("Content-Type: video/mp4\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(videoData)
body.append(String(format: kEndTag).data(using: String.Encoding.utf8)!)
// close form
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
return body
} catch let error {
print(error)
return nil
}
}
if let body = requestBodyFor(video: fileUrl) {
let contentType = "multipart/form-data; boundary=\(kBoundary)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.uploadTask(with: request, from: body) { data, response, error in
guard error == nil && data != nil else {
return
}
if let data = String(data: data!, encoding: String.Encoding.utf8) {
print(data)
}
}
task.resume()
}
uploadTask 是如何工作的?也许它将文件的数据附加到请求正文然后自动添加边界?如果我使用此代码,上传不起作用,我需要更改什么?
更新:我已经更新了代码,现在使用uploadTask的completionHandler在前台上传,但是如果我创建一个后台会话并使用URLSessionDataDelegate而不是completionHandler(因为它没有't work in the back),传输速度也很慢,2 MB的文件,我该如何解决这个问题?
更新 2:在后台会话中,uploadTask 多次重新启动,但从未完成,永远不会。
【问题讨论】:
-
使用 alamofire 。
-
如果可能的话,我不会使用任何外部框架来做到这一点
-
该示例显示 dataTask(它在后台不起作用)和 downloadTask,我需要工作 uploadTask 示例
-
后台任务需要配置。它不依赖于上传任务或数据任务。
标签: ios swift3 nsurlsessionuploadtask