繁体   English   中英

swift url Session 带有参数和图像的发布请求(多部分表单数据请求)

[英]swift url Session post request with parameters and image (Multipart Form-Data Requests )

我想使用 url session 将带有参数的图像发布到服务器,这是我尝试的 -

var groupImg: UIImage? 
 var grupId: String = ""
var grupName: String = ""
var creator: String = "xahiw"
var lati = "30.6425°N"
var long = "76.8173°E"

这是按钮操作的代码

@IBAction func onClickSubmitBtn(_ sender: Any) {
           let url = URL(string: "http://example/api/create")!
            var request = URLRequest(url: url)
            request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
            request.httpMethod = "POST"
            let parameters: [String: Any] = [
                "name": grupName,
                "category": grupId,
                "picture": groupImg!,
                "createdBy": creator,
                "lat": lati,
                "lng": long
    
            ]
            request.httpBody = parameters.percentEncoded()
    
            let task = URLSession.shared.dataTask(with: request) { data, response, error in
                guard let data = data,
                    let response = response as? HTTPURLResponse,
                    error == nil else {
                        print("error", error ?? "Unknown error")
                        return
                }
    
                guard (200 ... 299) ~= response.statusCode else {
                    print("statusCode should be 2xx, but is \(response.statusCode)")
                    print("response = \(response)")
                    return
                }
    
                let responseString = String(data: data, encoding: .utf8)
                print("responseString = \(String(describing: responseString))")
            }
    
            task.resume()
        
        
    }
    extension Dictionary {
        func percentEncoded() -> Data? {
            return map { key, value in
                let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
                let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
                return escapedKey + "=" + escapedValue
                }
                .joined(separator: "&")
                .data(using: .utf8)
        }
    }
    
    extension CharacterSet {
        static let urlQueryValueAllowed: CharacterSet = {
            let generalDelimitersToEncode = ":#[]@"
            let subDelimitersToEncode = "!$&'()*+,;="
    
            var allowed = CharacterSet.urlQueryAllowed
            allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
            return allowed
        }()
    }

但我无法发布数据我得到状态码 - 当我点击按钮时 400,谁能告诉我如何做到这一点,它是用不同的方式完成的(上传带有参数的图像)

您可以使用简单的 function 为您的请求创建正文。

func createBodyWithParameters(parameters: [String: String], filePathKey: String?, imageDataKey: Data?, boundary: String) -> Data {
    var body = Data();

    for (key, value) in parameters {
        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
        body.appendString("\(value)\r\n")
    }

    let filename = "image_name.jpg"
    let mimetype = "image/jpg"

    body.appendString("--\(boundary)\r\n")

    if let filePath = filePathKey, let imageData = imageDataKey {
        body.appendString("Content-Disposition: form-data; name=\"\(filePath)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.append(imageData)
        body.appendString("\r\n")
        body.appendString("--\(boundary)--\r\n")
    }

    return body
}

并将其分配给请求正文。

request.httpBody = createBodyWithParameters(parameters: ["key":"Value"], filePathKey: "file", imageDataKey: imageData, boundary: "Boundary-\(NSUUID().uuidString)");

要将字符串附加到数据中,您可以使用这样的扩展名。

extension Data {
    mutating func appendString(_ string: String) {
        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
        append(data!)
    }
}
class func request(withImages path:APIMethods, method:URLMethod, token : String?, headers:[String:String]?, parameters: [String:Any]?,imageNames : [String], images:[Data], completion: @escaping(Any?, Error?, Bool)->Void) {


    

    var stringUrl = “abc.com”
    if method == .get, let lastPath = parameters?.values.first as? String {
        stringUrl += lastPath
    }else{
        stringUrl += token ?? ""
    }


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

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    print("\n\ncomplete Url :-------------- ",stringUrl," \n\n-------------: complete Url")
    guard let url = URL(string: stringUrl) else { return }
    var request = URLRequest(url: url)
    request.httpMethod = method.rawValue

    if headers != nil{
        print("\n\nHeaders :-------------- ",headers as Any,"\n\n --------------: Headers")
        for (key, value) in headers! {
            request.setValue(value, forHTTPHeaderField: key)

        }
    }

    // Set Content-Type Header to multipart/form-data

    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    var data = Data()
    if parameters != nil{
        for(key, value) in parameters!{
          
            data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
            data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
            data.append("\(value)".data(using: .utf8)!)
        }
    }
    for (index,imageData) in images.enumerated() {
        
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"\(imageNames[index])\"; filename=\"\(imageNames[index])\"\r\n".data(using: .utf8)!)
        data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
        data.append(imageData)
    }

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

    
    session.uploadTask(with: request, from: data, completionHandler: { data, response, error in

        if let checkResponse = response as? HTTPURLResponse{
            if checkResponse.statusCode == 200{
                guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.allowFragments]) else {
                    completion(nil, error, false)
                    return
                }
                let jsonString = String(data: data, encoding: .utf8)!
                print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
                print(json)
                completion(json, nil, true)
            }else{
                guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
                    completion(nil, error, false)
                    return
                }
                let jsonString = String(data: data, encoding: .utf8)!
                print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
                print(json)
                completion(json, nil, false)
            }
        }else{
            guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
                completion(nil, error, false)
                return
            }
            completion(json, nil, false)
        }

    }).resume()

}

extension Data {


    mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
        if let data = string.data(using: encoding) {
            append(data)
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM