我正在尝试将个人资料图片上传到服务器。但是在做JSON Serialization
时我遇到了一个错误。
日志中的错误消息是:
[Generic]创建具有未知类型的图像格式是错误,
无法读取数据,因为格式不正确
从照片库中选择图像后,图像显示在用户界面中,但图像未成功上传到服务器,因此可能这就是我在进行JSON序列化时出错的原因。但我不知道为什么说不是正确的格式,因为我尝试上传jpeg格式的图像。
这是简化的代码。什么地方出了错? :(
import UIKit
class HomepageVC: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@IBAction func editProfilePictureButtonDidPressed(_ sender: Any) {
// users choose photo from library or camera
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
let actionSheet = UIAlertController(title: "Photo Source", message: "please choose your source", preferredStyle: .actionSheet)
// action camera
let actionCamera = UIAlertAction(title: "Camera", style: .default) { (action) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
} else {
self.showAlert(alertTitle: "Opppss", alertMessage: "camera can't be used / not available", actionTitle: "OK")
print("camera can't be used / not available")
}
}
// action photo library
let actionPhotoLibrary = UIAlertAction(title: "Photo Library", style: .default) { (action) in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}
//action cancel
let actionCancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(actionCamera)
actionSheet.addAction(actionPhotoLibrary)
actionSheet.addAction(actionCancel)
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
avatarImage.image = image
picker.dismiss(animated: true, completion: nil)
// call func of uploading file to PHP server
uploadAvatar()
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
// custom HTTP request body to upload image file
func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
var body = Data();
if parameters != nil {
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")
}
}
// kita set agar image yang di upload kemudian berformat .jpg
let filename = "avatar.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body as Data
}
// uploading image to server
func uploadAvatar() {
// get ID from Default variable
let id = userInfo!["id"] as! String
let url = URL(string: "http://localhost/Twitter/uploadAvatar.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let param = ["id" : id]
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(avatarImage.image!, 0.5)
// if not compressed, return ... do not continue to code
if imageData == nil {
return
}
// constructing http body
request.httpBody = createBodyWithParams(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)
// launc session
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async(execute: {
if error == nil {
// if error is nil, then show message from server
do {
// json containes $returnArray from php
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
// declare new parseJSON to store json
guard let parsedJSON = json else {
print("Error while parsing")
return
}
// get id from $returnArray["id"] in PHP - parseJSON["id"]
let id = parsedJSON["id"]
// successfully uploaded
if id != nil {
// save user information from Server
UserDefaults.standard.set(parsedJSON, forKey: "parsedJSON")
// if no ID from server then show the message from server
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = parsedJSON["message"] as! String
self.showAlert(alertTitle: "opppps", alertMessage: message, actionTitle: "OK")
})
}
// error doing JSON serialization
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error.localizedDescription
self.showAlert(alertTitle: "Sorry", alertMessage: message, actionTitle: "OK")
})
}
// error ketika koneksi ke server
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
self.showAlert(alertTitle: "oppps", alertMessage: message, actionTitle: "OK")
})
}
})
}.resume()
}
}
// extend data
extension Data {
mutating func appendString(_ string : String) {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
append(data!)
}
}
打印服务器数据以获取更多详细信息。像服务器错误或任何其他细节。
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async(execute: {
// server data is convert in to string and print it
let strData = String.init(data: data!, encoding: String.Encoding.utf8)
print(strData )
})
}
服务器返回的响应不是JSON格式。您可以使用该工具首先测试请求。
打印出错误代码不是HTTP错误代码,因为无法解析JSON