我需要在 post 請求中將表單資料發送到后端 URL。該表單包括字串、Int 值和影像。所以我關注了一篇博文并為它寫了一些代碼。
我首先創建了一個結構以及 3 個擴展:
struct MultipartFormDataRequest {
private let boundary: String = UUID().uuidString
private var httpBody = NSMutableData()
let url: URL
init(url: URL) {
self.url = url
}
func addTextField(named name: String, value: String) {
httpBody.append(textFormField(named: name, value: value))
}
private func textFormField(named name: String, value: String) -> String {
var fieldString = "--\(boundary)\r\n"
fieldString = "Content-Disposition: form-data; name=\"\(name)\"\r\n"
fieldString = "Content-Type: text/plain; charset=ISO-8859-1\r\n"
fieldString = "Content-Transfer-Encoding: 8bit\r\n"
fieldString = "\r\n"
fieldString = "\(value)\r\n"
return fieldString
}
func addDataField(named name: String, data: Data, mimeType: String) {
httpBody.append(dataFormField(named: name, data: data, mimeType: mimeType))
}
private func dataFormField(named name: String,
data: Data,
mimeType: String) -> Data {
let fieldData = NSMutableData()
fieldData.append("--\(boundary)\r\n")
fieldData.append("Content-Disposition: form-data; name=\"\(name)\"\r\n")
fieldData.append("Content-Type: \(mimeType)\r\n")
fieldData.append("\r\n")
fieldData.append(data)
fieldData.append("\r\n")
return fieldData as Data
}
func asURLRequest() -> URLRequest {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
httpBody.appendString("--\(boundary)--")
request.httpBody = httpBody as Data
return request
}
}
extension NSMutableData {
func append(_ string: String) {
if let data = string.data(using: .utf8) {
self.append(data)
}
}
}
extension NSMutableData {
func appendString(_ string: String) {
if let data = string.data(using: .utf8) {
self.append(data)
}
}
}
extension URLSession {
func dataTask(
with request: MultipartFormDataRequest,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void
)
-> URLSessionDataTask
{
return dataTask(
with: request.asURLRequest(),
completionHandler:
completionHandler)
}
}
在我的應用程式中,我有 2 個與 @Published 包裝器鏈接的文本欄位。int 值現在只是常量 1。還有一個用戶使用影像選擇器選擇的影像,然后這就是我上傳的方式。
func uploadForm() {
//myInt is a variable var myInt = 1, that's it
var sum = CreateAccountAuth.shared.userDetails?.id
let myIntData = Data(bytes: &myInt,
count: MemoryLayout.size(ofValue: myInt))
let myIntData2 = Data(bytes: &sum, count: MemoryLayout.size(ofValue: sum))
let request = MultipartFormDataRequest(url: URL(string: "my backend url")!)
request.addDataField(named: "product_image1", data: (self.image?.pngData())!, mimeType: "img/jpeg")
request.addTextField(named: "productName", value: self.artworkTitle)
request.addTextField(named: "producDescription", value: self.artworkDescription)
request.addDataField(named: "metauserID", data: myIntData2, mimeType: "Int")
request.addDataField(named: "product_categoryID", data: myIntData, mimeType: "Int")
request.addDataField(named: "discount_ID", data: myIntData, mimeType: "Int")
request.addDataField(named: "shop_ID", data: myIntData, mimeType: "Int")
request.addDataField(named: "boostTagsID", data: myIntData, mimeType: "Int")
let newRequest = request.asURLRequest()
let task = URLSession.shared.dataTask(with: newRequest) { data, value, error in
guard let data = data, error == nil else {
return
}
do {
guard let value = value as? HTTPURLResponse else {return}
if value.statusCode >= 200 && value.statusCode < 300 {
print("good")
}
else if value.statusCode >= 300 {
print("bad")
}
let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(response)
} catch {
print(error)
}
}
task.resume()
}
}
當我在添加一些文本和影像后通過按鈕觸發此功能時,我收到錯誤訊息:
錯誤域 = NSCocoaErrorDomain 代碼 = 3840 “無法決議空資料。” UserInfo={NSDebugDescription=無法決議空資料。}
我也嘗試使用 alamofire,但找不到關于上傳字串以外的資料的有用博客。
uj5u.com熱心網友回復:
我想到了,
首先,我應該檢查一下
var sum = CreateAccountAuth.shared.userDetails?.id
是否為 nil,事實證明它是 nil,我將使用 UserDefaults 從現在開始存盤該 Int 值以保持它
其次,表單同時接受 Int 和 String 作為 Text,這意味著我撰寫的將 Int 轉換為資料的代碼不需要簡單地使用字串插值來撰寫
"\(Integer)"
第三,每當發送影像時,我們需要給它一個檔案名,我的代碼沒有它,所以它失敗了
所以這是修改后的代碼,我現在正在使用 Alamofire,因為它更容易
func uploadPost() {
guard let imageData = self.image?.jpegData(compressionQuality: 1) else {
print("the image data is empty")
return}
AF.upload(multipartFormData: { (multipartdata) in
multipartdata.append("\(2)".data(using: String.Encoding.utf8)!, withName: "metauserID")
multipartdata.append("\(1)".data(using: String.Encoding.utf8)!, withName: "boostTagsID")
multipartdata.append("\(1)".data(using: String.Encoding.utf8)!, withName: "shop_ID")
multipartdata.append("\(1)".data(using: String.Encoding.utf8)!, withName: "discount_ID")
multipartdata.append("\(1)".data(using: String.Encoding.utf8)!, withName: "product_categoryID")
multipartdata.append(self.artworkDescription.data(using: String.Encoding.utf8)!, withName: "producDescription")
multipartdata.append(self.artworkTitle.data(using: String.Encoding.utf8)!, withName: "productName")
multipartdata.append(imageData, withName: "product_image1", fileName: "\(UUID().uuidString) .png", mimeType: "img/jpeg")
//multipartdata.append("\()", withName: "metauderID")
}, to: "my Backend URL").responseJSON { (data) in
print(data)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/498366.html
