The fundamental issue is that your x-www-form-urlencoded
request is not well-formed. You have explicitly requested it to create base64 string with newline characters in it, but those are not allowed in x-www-form-urlencoded
unless you percent encode them. Plus, we don't know what sort of characters are inside message
.
I would suggest:
- Not request newline characters to be added to the base64 string unless you really needed them; but
- Percent escape the string values, anyway, as I don't know what sort of values you have for
message
.
Thus:
let parameters = [
"message": message,
"encoded_img": convertToBase64(image: image1.image!)
]
let session = URLSession.shared
let url = URL(string: "http://xxxxxx/msg.php")!
var request = URLRequest(url: url, timeoutInterval: 20.0)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") // not necessary, but best practice
request.setValue("application/json", forHTTPHeaderField: "Accept") // again, not necessary, but best practice; set this to whatever format you're expecting the response to be
request.httpBody = parameters.map { key, value in
let keyString = key.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
let valueString = value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
return keyString + "=" + valueString
}.joined(separator: "&").data(using: .utf8)
let dataTask = session.dataTask(with:request) { data, response, error in
guard error == nil,
let data = data,
let httpResponse = response as? HTTPURLResponse,
(200 ..< 300) ~= httpResponse.statusCode else {
print(error ?? "Unknown error", response ?? "Unknown response")
return
}
// process `data` here
}
dataTask.resume()
where
func convertToBase64(image: UIImage) -> String {
return UIImagePNGRepresentation(image)!
.base64EncodedString()
}
and
extension CharacterSet {
/// Character set containing characters allowed in query value as outlined in RFC 3986.
///
/// RFC 3986 states that the following characters are "reserved" characters.
///
/// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
/// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
///
/// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
/// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
/// should be percent-escaped in the query string.
///
/// - parameter string: The string to be percent-escaped.
///
/// - returns: The percent-escaped string.
static var urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}
Alternatively, you could consider using Alamofire which gets you out of the weeds of creating well-formed x-www-form-urlencoded
requests.