I’m implementing resumable uploads on iOS based on this documentation and wwdc video
The server correctly sends a 104 Upload Resumption Supported informational response, which I receive in my delegate. However, when I cancel the upload task using cancelByProducingResumeData(), it always returns nil.
Setup
- iOS 18/26
- HTTP/2 server with TLS (using SwiftNIO + Network.framework)
- Server implements the resumable upload draft protocol
Client Code
class VideoUploader: NSObject, URLSessionTaskDelegate, URLSessionDataDelegate {
private var urlSession: URLSession!
private var uploadTask: URLSessionUploadTask?
func uploadVideo(fileURL: URL) {
var request = URLRequest(url: URL(string: "
request.httpMethod = "POST"
request.setValue("?0", forHTTPHeaderField: "Upload-Incomplete")
request.setValue("3", forHTTPHeaderField: "Upload-Draft-Interop-Version")
uploadTask = urlSession.uploadTask(with: request, fromFile: fileURL)
uploadTask?.resume()
// Cancel after 3 seconds to test resume data
Task {
try? await Task.sleep(for: .seconds(3))
guard let uploadTask else { return }
let resumeData = await uploadTask.cancelByProducingResumeData()
print("Resume data: \(resumeData)") // Always prints nil
}
}
// This IS called - server sends 104 correctly
func urlSession(_ session: URLSession, task: URLSessionTask, didReceiveInformationalResponse response: HTTPURLResponse) {
print("Received 104: \(response.statusCode)")
print("Location: \(response.allHeaderFields["Location"] ?? "none")")
}
}
Here’s a repo with server side code and app that reproduces the issue.
Any idea what I could be missing, or even how I could debug this?