首页 > 解决方案 > 如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?

问题描述

我需要通过 REST api(表单数据)发布方法上传带有其他值的图像。我已经通过下面的代码从图库中获取了图像。

    ZStack {
        VStack {
            Button(action: {
                self.showImagePicker.toggle()
            }) {
                Text("Choose your file")
            }
            image?.resizable().frame(width: 100, height: 100)
        }
        .sheet(isPresented: $showImagePicker) {
            ImagePicker(sourceType: .photoLibrary) { image in
                self.image = Image(uiImage: image)
                
                
            }
        }
    }

我必须通过此 API 调用发送其他值,例如“studentPaymentTypeId”。作为 SwiftUI 的新手,我对 SwiftUI 如何处理多部分 REST API 调用感到困惑。我附上了我想要实现的工作 API 的邮递员屏幕截图。

在此处输入图像描述

现在,如何通过 REST api post 方法将带有所有其他参数的图像文件发送到服务器?

我尝试了下面的代码但无法正常工作!

func uploadReceipt(image: UIImage) {
        
        let token = UserDefaults.standard.string(forKey: "login_token")
        
        
        // create post request

        
        guard let url = URL(string: "my url") else {
            print("Invalid URL")
            return
        }
        

        // generate boundary string using a unique per-app string
        let boundary = UUID().uuidString

        let session = URLSession.shared

        // Set the URLRequest to POST and to the specified URL
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = "POST"
        
        urlRequest.allHTTPHeaderFields = [
            //"Content-Type": "application/json",
            //"Accept": "application/json",
            "Authorization": "Bearer "+token!
        ]

        // Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
        // And the boundary is also set here
        urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        var data = Data()

        // Add the image data to the raw http request data
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; studentPaymentTypeId=\"\(1)\";classTermId=\"\(1)\";sessionId=\"\(1)\"; attachmentFile=\"\(imageToSent!)\"\r\n".data(using: .utf8)!)
        data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
       
        data.append(image.pngData()!)

        data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)

        // Send a POST request to the URL, with the data we created earlier
        session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
            if error == nil {
                let jsonData = try? JSONSerialization.jsonObject(with: responseData!, options: .allowFragments)
                if let json = jsonData as? [String: Any] {
                    print(json)
                }
            }
        }).resume()
    }
                                            
                 

标签: iosswiftxcoderest

解决方案


通过使用Alamofire,我设法上传了多部分表单数据。

这是下面的代码:

import Alamofire

. . .

func uploadReceipt(){
        
        
        let token = UserDefaults.standard.string(forKey: "login_token")
        
        let headers: HTTPHeaders = [
            .authorization("Bearer "+token!),
            .accept("application/json")
            
        ]
        
        
        AF.upload(multipartFormData: { multipartFormData in
            
            
            multipartFormData.append(imageToSent!.jpegData(compressionQuality: 1)!, withName: "attachmentFile", fileName: "someFile.jpg", mimeType: "image/jpeg")
            multipartFormData.append("1".data(using: .utf8)!, withName :"studentPaymentTypeId")
            multipartFormData.append("1".data(using: .utf8)!, withName :"classTermId")
            multipartFormData.append("1".data(using: .utf8)!, withName :"sessionId")
            
        }, to: "https://lms.learnerscafe.com/api/payment", method: .post, headers: headers)
        .responseJSON { response in
            switch response.result {
            case .success:
                
                print("Validation Successful)")
                
                
            case .failure(let error):
                
                print(error)
                
                
            }
            
           
        }
        
    }

推荐阅读