'Swift: Send image inside post request and associated flow architecture

Essentially what I am trying to do is this:

The user takes a picture/chooses from photo gallery. This picture is then sent to my backend. Here's my first issue: including the image in an encodable package. Is this possible? On the backend, I'm going to first do some databasing to get a generated 'id' for the picture. Then I'll be uploading the picture to S3 using the id as part of the object URL. Once the upload is complete, I'll be adding the URL to a column in the database (so the row will have an 'id' and an associated S3 URL. Is this a decent/not nooby way of doing this? Is there a better way?

My table in the database looks like:

| id |    s3_url    | 
| 0  |  https://... |
| 1  |  https://... |
| .  |  ........... |
| .  |  ........... |
| n  |  https://... |

My function to send the information is pretty standard, but I'm not sure how to include the image in the package (the struct 'Package' cannot conform to Codable if it has a UIImage in it):

func postRequest(string: String, number: Int, image: UIImage) {

    let server = 'serverURL'
    
    let package = Package(string: string, number: number, image: image) // passing in strings and numbers works fine, but not images?
    
    guard let url  = URL(string: server) else { return }

    var urlRequest = URLRequest(url: url)
    
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    
    urlRequest.httpMethod = "POST"
    
    guard let data = try? JSONEncoder().encode(package) else { return }
            
    urlRequest.httpBody = data

    let task = URLSession.shared.dataTask(with: urlRequest) {
        (data, response, error) in
        if let error = error {
            //print(error)
            return
        }
        guard let data = data else { return }
        guard let dataString = String(data: data, encoding: String.Encoding.utf8) else {return}
        
        DispatchQueue.main.async {
            //do stuff on return of data
        }
    }
    // start the task
    task.resume()
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source