SwiftUI,如何在使用 await urlSession.upload(...) 上传 multipart/form-data 文件时取得进展
SwiftUI, how to get progress whilst uploading multipart/form-data files using await urlSession.upload(...)
iOS15+
如何使用 await urlSession.upload 从以下获取上传进度?
我特别想要使用 urlSession.uploadTask 似乎无法获得(或理解如何)的等待功能。
代码上传文件正常。
我试过在底部使用 urlSession 函数,但它从未触发。
https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1408299-urlsession
请注意,我通常使用 C# 编写代码,而且我主要是 swift 的初学者。
谢谢。
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))")
}
}
回答我自己的问题。
如果有人发现任何错误或不良做法,请随时发表评论。
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))")
}
}
iOS15+
如何使用 await urlSession.upload 从以下获取上传进度?
我特别想要使用 urlSession.uploadTask 似乎无法获得(或理解如何)的等待功能。
代码上传文件正常。
我试过在底部使用 urlSession 函数,但它从未触发。
https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1408299-urlsession
请注意,我通常使用 C# 编写代码,而且我主要是 swift 的初学者。
谢谢。
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))")
}
}
回答我自己的问题。
如果有人发现任何错误或不良做法,请随时发表评论。
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))")
}
}