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

问题描述 投票:1回答:1

我正在尝试将个人资料图片上传到服务器。但是在做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!)

    }

}
ios swift
1个回答
1
投票

打印服务器数据以获取更多详细信息。像服务器错误或任何其他细节。

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

© www.soinside.com 2019 - 2024. All rights reserved.