0

I am trying to solve how to upload a set of parameters and an image file to my API using swift.

My code is roughly at about this point:

//parameters
    let actualParameters = ["email": myEmail, "token": myToken, "certnbr": certnbr, "title": title, "newCert": newCert, "expires": expires, "expiryDate": expiryDate, "issueDate": issueDate] as! [String : Any]

    let parameters = NewCertModel(email: "email")

    //create the url with URL
    let url = URL(string: "http://127.0.0.1:8000/api/newCertification/")!

    //now create the URLRequest object using the url object
    var request = URLRequest(url: url)

    request.httpMethod = "POST"
    let boundary = "Boundary-\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    request.httpBody = createBody(parameters: params,
                            boundary: boundary,
                            data: UIImageJPEGRepresentation(chosenImage, 0.7)!,
                            mimeType: "image/jpg",
                            filename: "hello.jpg")

    guard let uploadData = try? JSONEncoder().encode(parameters) else {
        print("Error Upload Data")
        return
    }


    //new session
    URLSession.shared.uploadTask(with: request as URLRequest, from: jsonData as! Data) { (responseData, response, error) in
                                    // Check on some response headers (if it's HTTP)
                                    if let httpResponse = response as? HTTPURLResponse {
                                        switch httpResponse.statusCode {
                                        case 200..<300:
                                            print("Success")
                                        case 400..<500:
                                            print("Request error")
                                        case 500..<600:
                                            print("Server error")
                                        case let otherCode:
                                            print("Other code: \(otherCode)")
                                        }
                                    }

                                    // Do something with the response data
                                    if let
                                        responseData = responseData,
                                        let responseString = String(data: responseData, encoding: String.Encoding.utf8) {
                                        print("Server Response:")
                                        print(responseString)
                                    }

                                    // Do something with the error
                                    if let error = error {
                                        print(error.localizedDescription)
                                    }
    }

    .resume()
    }
}

The code isn't perfect because I've tried quite a few solutions and they are now a bit jumbled. I am able to easily pass data to my api, but the file uploading/multi-part has stumped me. I am finding the resources for this very difficult to find and limited, especially coming from a full time Android development position.

I could switch to Alamofire but my entire project isn't using it yet. I would like to wait to switch over. I've easily spent 5 hours trying combinations to even show the slightest passed data but nothing yet.

Here is the start to my python code:

if request.method == 'POST':

email = request.POST.get('email')
token = request.POST.get('token')
certnbr = request.POST.get('certnbr')
title = request.POST.get('title')
newCert = request.POST.get('newCert')
expires = request.POST.get('expires')
expirydate = request.POST.get('expiryDate')
issuedate = request.POST.get('issueDate')
picfile = request.FILES.get('image')

data = {}

#get the user
u = Usr.objects.get(email__iexact=email)

Some sources I had no luck with:

fluffy.es - "This code looks so sloppy to me?"

medium article - "I couldn't find a hint of parameter passing here"

stackoverflow

more stackoverflow

further stackoverlow

What surprises me is this inconsistancy between all these sources, only a few even use uploadTask, plus I read a dozen others that seemed to be different. Ultimately is Alamofire the best choice? Why wouldn't Apple just adopt it? This whole process is surprisingly difficult, thank for any help in advance.

EDIT: I switched to Alamofire, instantly easier.

C. Skjerdal
  • 2,750
  • 3
  • 25
  • 50

1 Answers1

0

While not the best answer to my question, the Alamofire code is just cleaner. So to save any future me some stress. Just use Alamofire.

Alamofire Github

let ImageData = imageobj.pngData()
    let urlReq = URL(string: "http://127.0.0.1:8000/api/newCertification/")!
    print("params")
    let params : Parameters = ["email": myEmail, "token": myToken, "certnbr": certnbr, "title": title, "newCert": newCert, "expires": expires, "expiryDate": expiryDate as Any, "issueDate": issueDate as Any]
    print("time to upload")
    Alamofire.upload(multipartFormData: { multipartFormData in
        multipartFormData.append(ImageData!, withName: "avatar",fileName: "file.jpg", mimeType: "image/jpg")
        for (key, value) in params {// this will loop the 'parameters' value, you can comment this if not needed
            multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
        }
    },
                     to:urlReq)
    { (result) in
        switch result {
        case .success(let upload, _, _):

            upload.uploadProgress(closure: { (progress) in
                print("Upload Progress: \(progress.fractionCompleted)")
            })

            upload.responseJSON { response in
                //completion("success")
            }

        case .failure(let encodingError):
            print(encodingError)
            //completion("failed")


    }
}
C. Skjerdal
  • 2,750
  • 3
  • 25
  • 50