iOS 15+
How do I get the upload progress from the following using await urlSession.upload?
I specifically want the Await functionality which I dont seem to get (or understand how to) using urlSession.uploadTask.
The code uploads the file fine.
I've tried using the urlSession function at the bottom but it never fires.
https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1408299-urlsession
Please note I normally code C# and I am mostly a beginner in swift.
Thank you.
NetworkManager.swift
import SwiftUI
class NetworkManager {
static let shared = NetworkManager()
private init() {}
func uploadZipFile (
zipFileURL: URL) async throws -> (Data, URLResponse) {
let name: String = zipFileURL.deletingPathExtension().lastPathComponent
let fileName: String = zipFileURL.lastPathComponent
let zipFileData: Data?
do {
zipFileData = try Data(contentsOf: zipFileURL)
} catch {
throw error
}
let uploadApiUrl: URL? = URL(string: "https://someapi.com/upload")
// Generate a unique boundary string using a UUID.
let uniqueBoundary = UUID().uuidString
var bodyData = Data()
// Add the multipart/form-data raw http body data.
bodyData.append("\r\n--\(uniqueBoundary)\r\n".data(using: .utf8)!)
bodyData.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
bodyData.append("Content-Type: application/zip\r\n\r\n".data(using: .utf8)!)
// Add the zip file data to the raw http body data.
bodyData.append(zipFileData!)
// End the multipart/form-data raw http body data.
bodyData.append("\r\n--\(uniqueBoundary)--\r\n".data(using: .utf8)!)
let urlSessionConfiguration = URLSessionConfiguration.default
let urlSession
= URLSession(
configuration: urlSessionConfiguration,
delegate: nil, // Something I need here maybe?
delegateQueue: nil)
var urlRequest = URLRequest(url: uploadApiUrl!)
// Set Content-Type Header to multipart/form-data with the unique boundary.
urlRequest.setValue("multipart/form-data; boundary=\(uniqueBoundary)", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = "POST"
let (data, urlResponse) = try await urlSession.upload(
for: urlRequest,
from: bodyData,
delegate: nil // Something I need here maybe?
)
return (data, urlResponse)
}
// Tried this but it never fires.
func urlSession(
_ session: URLSession,
task: URLSessionTask,
didSendBodyData bytesSent: Int64,
totalBytesSent: Int64,
totalBytesExpectedToSend: Int64) {
print("fractionCompleted : \(Float(totalBytesSent) / Float(totalBytesExpectedToSend))")
}
}
Answering my own question.
If anybody sees anything thats wrong or bad practice then please feel free to comment.
NetworkManager.swift
import SwiftUI
class NetworkManager: NSObject {
static let shared = NetworkManager()
private override init() {}
func uploadZipFile (
zipFileURL: URL) async throws -> (Data, URLResponse) {
let name: String = zipFileURL.deletingPathExtension().lastPathComponent
let fileName: String = zipFileURL.lastPathComponent
let zipFileData: Data?
do {
zipFileData = try Data(contentsOf: zipFileURL)
} catch {
throw error
}
let uploadApiUrl: URL? = URL(string: "https://someapi.com/upload")
// Generate a unique boundary string using a UUID.
let uniqueBoundary = UUID().uuidString
var bodyData = Data()
// Add the multipart/form-data raw http body data.
bodyData.append("\r\n--\(uniqueBoundary)\r\n".data(using: .utf8)!)
bodyData.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
bodyData.append("Content-Type: application/zip\r\n\r\n".data(using: .utf8)!)
// Add the zip file data to the raw http body data.
bodyData.append(zipFileData!)
// End the multipart/form-data raw http body data.
bodyData.append("\r\n--\(uniqueBoundary)--\r\n".data(using: .utf8)!)
let urlSessionConfiguration = URLSessionConfiguration.default
let urlSession
= URLSession(
configuration: urlSessionConfiguration,
delegate: self,
delegateQueue: nil)
var urlRequest = URLRequest(url: uploadApiUrl!)
// Set Content-Type Header to multipart/form-data with the unique boundary.
urlRequest.setValue("multipart/form-data; boundary=\(uniqueBoundary)", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = "POST"
let (data, urlResponse) = try await urlSession.upload(
for: urlRequest,
from: bodyData,
delegate: nil
)
return (data, urlResponse)
}
}
extension NetworkManager: URLSessionTaskDelegate {
func urlSession(
_ session: URLSession,
task: URLSessionTask,
didSendBodyData bytesSent: Int64,
totalBytesSent: Int64,
totalBytesExpectedToSend: Int64) {
print("fractionCompleted : \(Int(Float(totalBytesSent) / Float(totalBytesExpectedToSend) * 100))")
}
}