Ror*_*ran 1 ios nsurlsessionuploadtask swift3
我需要将iPhone / iPad上的mp4视频文件上传到服务器(也在后台),所以我读到可以通过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(因为它在后台不起作用),则传输2 MB文件的传输速度也很慢,我该如何解决?
更新2:在后台会话中,uploadTask会重新启动很多次,并且永远不会完成。
经过一些尝试后,我看到URLSession.uploadTask(with:URLRequest,fromFile:URL)方法将文件作为原始主体附加到请求中,因此问题出在解析表单数据请求而不是原始主体请求的服务器副本中。我修复了服务器端脚本,使用以下代码在后台运行上传:
    var request = URLRequest(url: "my_url")
    request.httpMethod = "POST"
    request.setValue(file.lastPathComponent, forHTTPHeaderField: "filename")
    let sessionConfig = URLSessionConfiguration.background(withIdentifier: "it.example.upload")
    sessionConfig.isDiscretionary = false
    sessionConfig.networkServiceType = .video
    let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
    let task = session.uploadTask(with: request, fromFile: file)
    task.resume()