代码之家  ›  专栏  ›  技术社区  ›  Agung

执行JSON序列化时出错,数据格式不正确

  •  1
  • Agung  · 技术社区  · 7 年前

    我正在尝试将个人资料图片上载到服务器。但我做的时候出错了 JSON Serialization .

    日志中的错误消息为 :

    [通用]创建类型未知的图像格式时出错,

    无法读取数据,因为它的格式不正确

    从照片库中选择图像后,图像会显示在用户界面中,但图像没有成功上载到服务器,所以这可能就是我在执行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!)
    
        }
    
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   AshvinGudaliya    7 年前

    有关详细信息,请打印服务器数据。如服务器错误或任何其他详细信息。

    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格式。您可以先使用该工具测试请求。

    由于无法解析JSON,打印出的错误代码不是HTTP错误代码