0

Well, i need to send path of photo file, but i always have Fatal error: Unexpectedly found nil while unwrapping an Optional value. Here what a post request looks like:

let parameters = [
  [
    "key": "description",
    "value": "Hello",
    "type": "text",
    "contentType": "text/plain"
  ],
  [
    "key": "photo",
    "src": "/path/to/file",
    "type": "file"
  ],
  [
    "key": "rate",
    "value": "{  
  \"availability\": 1,
  \"beauty\": 2,
  \"purity\": 3
}",
    "type": "text"
  ],
  [
    "key": "results",
    "value": "[{ 
  \"waste_id\":{\"name\": \"Крышечки\",
  \"unit_of_waste\": \"шт\"},
  \"amount\": 10
}]
",
    "type": "text"
  ],
  [
    "key": "report_status",
    "value": "Accept",
    "type": "text"
  ],
  [
    "key": "point_id",
    "value": "",
    "type": "text"
  ],
  [
    "key": "type_obj",
    "value": "route",
    "type": "text"
  ],
  [
    "key": "id_obj",
    "value": "",
    "type": "text"
  ]] as [[String: Any]]

let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
  if param["disabled"] != nil { continue }
  let paramName = param["key"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if param["contentType"] != nil {
    body += "\r\nContent-Type: \(param["contentType"] as! String)"
  }
  let paramType = param["type"] as! String
  if paramType == "text" {
    let paramValue = param["value"] as! String
    body += "\r\n\r\n\(paramValue)\r\n"
  } else {
    let paramSrc = param["src"] as! String
    let fileData = try NSData(contentsOfFile: paramSrc, options: []) as Data
    let fileContent = String(data: fileData, encoding: .utf8)!
    body += "; filename=\"\(paramSrc)\"\r\n"
      + "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
  }
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)

var request = URLRequest(url: URL(string: "http://somehost:8000/report/create_report/")!,timeoutInterval: Double.infinity)
request.addValue("Bearer some key", forHTTPHeaderField: "Authorization")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

request.httpMethod = "POST"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in 
  guard let data = data else {
    print(String(describing: error))
    return
  }
  print(String(data: data, encoding: .utf8)!)
}

task.resume()

I select a photo from the imagePicker, save it, then send the path, but it keeps crashing that nill was found:

Here's my implementation:

extension ReportViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        guard let image = info[.originalImage] as? UIImage else {
            dismiss(animated: true, completion: nil)
            return
        }
        
        // Store the selected image
        selectedImage = image
        
        dismiss(animated: true, completion: nil)
    }
    
    func saveImageToFile(_ image: UIImage) -> String? {
        guard let imageData = image.jpegData(compressionQuality: 1.0) else {
            print("Failed to convert image to JPEG data")
            return nil
        }
        
        let fileManager = FileManager.default
        let temporaryDirectory = NSTemporaryDirectory()
        let fileName = UUID().uuidString + ".jpeg"
        let fileURL = URL(fileURLWithPath: temporaryDirectory).appendingPathComponent(fileName)
        
        do {
            try imageData.write(to: fileURL)
            return fileURL.path
        } catch {
            print("Failed to save image to file: \(error)")
            return nil
        }
    }
}

and this is how i send this in body of post request:

guard let image = selectedImage else {
            print("No image selected")
            return
        }
        
        guard let fileURL = saveImageToFile(image) else {
            print("Failed to save image to file")
            return
        }
        
        guard let filePath = fileURL.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else {
            print("Failed to encode file path")
            return
        }

           [
                "key": "photo",
                "src": filePath,
                "type": "file"
            ],

Error show's here: let fileContent = String(data: fileData, encoding: .utf8)!

Thanks for answering!

HangarRash
  • 7,314
  • 5
  • 5
  • 32
  • Not all Data can be converted into UTF8 String, there are combinaison of bits that don't make UTF8 valid characters. `var body = ""` should be `var body = Data()`, and then you append data. For the "string part" you can do `body += Data(aString.utf8)`, and for the file `body += fileData` – Larme Jun 10 '23 at 10:12
  • @Larme sorry but i don't understand what i need to change – Alexander Chebotarev Jun 10 '23 at 10:27
  • Here: `var body = ""`, `body` is a `String`. Make it a `Data` object instead: `var body = Data()`, and update your code.` – Larme Jun 11 '23 at 10:33

0 Answers0