如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?

Posted

技术标签:

【中文标题】如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?【英文标题】:How to post image and other parameters as form data via REST api with Swift URLSession? 【发布时间】:2021-03-29 06:31:47 【问题描述】:

我需要通过 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()
    
                                            
                 

【问题讨论】:

【参考方案1】:

通过使用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)
                
                
            
            
           
        
        
    

【讨论】:

以上是关于如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?的主要内容,如果未能解决你的问题,请参考以下文章

通过证书进行客户端身份验证的 Swift 3 UrlSession

如何在 Swift 3 中使用带有代理的 URLSession

如何使用 URLSession 解析并将它们导入 Swift 的数组中?

Swift:如何在异步 urlsession 函数中返回一个值?

Swift:如何在异步 urlsession 函数中返回一个值?

Swift 重复 URLSession 造成大量内存泄漏