2

I uploaded an image using almofire and it is being uploaded to the correct path I require.

However, I need to get some of the responses that are in my PHP backend code into my swift such as the filepath.

An image to make my question more clear and precise about what I want to get from the .responseJSON

In the image below is my response from the PHP code, I want to get the value of the filepath in swift. How can I achieve that?

enter image description here

Here is my code:

PHP:

<?php

if (empty($_FILES["image"])) {
    $response = array("error" => "nodata");
}

else {
    $response['error'] = "NULL";
   
    $filename = uniqid() . ".jpg";
 
    if (move_uploaded_file($_FILES['image']['tmp_name'], "../propertyImages/" . $filename)) {
   
        $response['status'] = "success";
        $response['filepath'] = "https://example.com/WebService/propertyImages/" . $filename;
        $response['filename'] = "".$_FILES["file"]["name"];

} else{
   
    $response['status'] = "Failure";
    $response['error']  = "".$_FILES["image"]["error"];
    $response['name']   = "".$_FILES["image"]["name"]; 
    $response['path']   = "".$_FILES["image"]["tmp_name"];
    $response['type']   = "".$_FILES["image"]["type"];
    $response['size']   = "".$_FILES["image"]["size"];
  }
}

echo json_encode($response);
?>

Swift Code:

 self.imageData = propImage.image!.jpegData(compressionQuality: 0.5)!
        
        let headers: HTTPHeaders = [
                    "Content-type": "multipart/form-data"
                ]

                    AF.upload(
                        multipartFormData: { multipartFormData in
                            multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")
                    },
                        to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers)
                        .responseJSON { resp in
                            //let responseString: String = String(data: self.imageData!, encoding: .utf8)!
                            print(resp) //this prints all the responses from the PHP code, my problem is how do i get a specific response, such as the filepath only and so on?
            }

EDIT:

I tried some of the solutions, this one seems to be the one that will work but still gives an error reading

"No exact matches in call to class method 'jsonObject'"

Updated code:

AF.upload(multipartFormData: { multipartFormData in                           multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")},                      to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers).responseJSON {
   result in
                        
 do{
   if let jsonResults = try JSONSerialization.jsonObject(with: result, options: []) as? [String: Any] { //error in this line
 let filePath = jsonResults["filepath"] as? String 
                            }
          }catch{
         print("ERROR")
     }
motionless570
  • 925
  • 1
  • 10
  • 26
  • try print(rep.filepath) – Aqib Javed Jan 26 '22 at 09:34
  • @AqibJaved this is what i get an error that says, `Value of type 'AFDataResponse' (aka 'DataResponse') has no member 'filepath'` – motionless570 Jan 26 '22 at 09:35
  • @AqibJaved and how can i do that? – motionless570 Jan 26 '22 at 09:40
  • It's already decoded. You need to use a switch on `resp`, in case of success, you can cast the value as `[String: Any]`, and retrieve the value... – Larme Jan 26 '22 at 09:41
  • @Larme can you please give a detailed answer/example? – motionless570 Jan 26 '22 at 09:43
  • You need to understand `Result`, see the doc https://developer.apple.com/documentation/swift/result/writing_failable_asynchronous_apis It's really commonly used. Then, the value is a `Any`, but can be casted as `[String: Any]`, so it's just a dictionary afterwards – Larme Jan 26 '22 at 09:55
  • @Larme you cant post an answer please? i am getting errors for everything i try – motionless570 Jan 26 '22 at 10:14
  • Does this answer your question? [How to parse JSON response from Alamofire API in Swift?](https://stackoverflow.com/questions/26114831/how-to-parse-json-response-from-alamofire-api-in-swift) – Simon McLoughlin Jan 26 '22 at 11:03
  • @SimonMcLoughlin no, as you can see from my code i am using a different way. i am using `AF.upload` not `Almofire.request.` and both are a bit different in how to handle the parsing of json and retrieving the data – motionless570 Jan 26 '22 at 11:10
  • `result` is not a `Data`, that's why you are getting the error. – Larme Jan 26 '22 at 13:39

2 Answers2

0

Then just decode your response:

if let jsonResults = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
    let filePath = jsonResults["filepath"] as? String // here is your value
}
AlexM
  • 317
  • 2
  • 5
  • Why use `JSONSerialization` if while using `.responseJSON`, there was already a call to `JSONSerialization`? That's doing twice the job... – Larme Jan 26 '22 at 13:40
-1

The value of the responseJSON block, is a Result. It's a basic concept used frequently, so you need to learn how do handle it. Common practice is then to use a switch.

let headers: HTTPHeaders = ["Content-type": "multipart/form-data"]

AF.upload(multipartFormData: { multipartFormData in
    multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")
                             },
                              to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers)
   .responseJSON { result in
    switch result {
        case .success(let json):
            guard let dictionary = json as? [String: Any] else { print("Response JSON is not a dictionary"); return }
            guard let filePath = json["filePath"] as? String else { print("filePath key is not present in "\(json)" or is not a String");  return }
            print("Filepath: \(filePath)")
        case .failure(let error):
            print("Error: \(error)")
    }

}

Now, it might be better to use a Codable struct to parse your response and call responseDecodable() instead of using responseJSON() which will use JSONSerialization, method which is by the way deprecated and will be removed in next Alamofire major release.

Larme
  • 24,190
  • 6
  • 51
  • 81