我想通过 url 会话将带有参数的图像发布到服务器,这是我尝试的 -
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,谁能告诉我如何做到这一点,是否以不同的方式完成(上传带有参数的图像)
答案 0 :(得分:1)
您可以使用一个简单的函数为您的请求创建一个正文。
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!)
}
}
答案 1 :(得分:0)
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)
}
}
}