0

I'm trying to upload an image to a server in iOS using Swift 3, I've tried with Alamofire but it's not working, so I just searched for another solution here in this forum but without luck.

I found some answers that said that the problem could have been server side, but, on Android the image is uploading correctly.

This is my upload function in swift 3:

func uploadImage(image: UIImage){
         let imageData = UIImageJPEGRepresentation(image, 0.1)!

         let session = URLSession(configuration: URLSessionConfiguration.default)

         guard let url = URL(string: uploadPicUrl) /* your API url */) else { return }
         var request = URLRequest(url: url)

         request.httpMethod = "POST"

         let boundary = "---------------------------14737809831466499882746641449"
         let contentType = "multipart/form-data; boundary=\(boundary)"
         request.addValue(contentType, forHTTPHeaderField: "Content-Type")

         var body = Data()
         body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
         body.append("Content-Disposition: form-data; name=\"userfile\"; filename=\"img.jpg\"\r\n".data(using: String.Encoding.utf8)!)
         body.append("Content-Transfer-Encoding: binary\r\n\r\n".data(using: String.Encoding.utf8)!)
         body.append(imageData)
         body.append("\r\n".data(using: String.Encoding.utf8)!)
         body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)

         request.httpBody = body

         print("request", request.debugDescription)
         print("body", body.debugDescription)

         let dataTask = session.dataTask(with: request) { (data, response, error) in

         if let error = error {
         print("Something went wrong: \(error)")
         }

         if let response = response {
         print("Response: \n \(response)")
         }
         }

         dataTask.resume()
}

2 Answers2

0

Without using Alamofire, you can do the following:

func uploadImage(chosenimage: UIImage) {

    let url = ApiList.base_url + ApiList.uploadFile_Url
    let myUrl = NSURL(string: url)
    let image_data = UIImagePNGRepresentation(chosenimage)
    let tempData = NSMutableData()
    let request = NSMutableURLRequest(url:myUrl! as URL)
    request.httpMethod = "POST"
    let boundary = NSUUID().uuidString
    request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField:"Content-Type")
    let mimetype = "image/png"
    let fname = "test.png"
    self.body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    self.body.append("Content-Disposition:form-data; name=\"profileUrl\"; filename=\"\(fname)\"\r\n".data(using: String.Encoding.utf8)!)
    self.body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
    self.body.append(image_data!)
    self.body.append("\r\n".data(using: String.Encoding.utf8)!)

    let accessToken = UserDefaults.standard.value(forKey: "accessToken") as? String ?? ""
    let deviceToken = UserDefaults.standard.value(forKey: "deviceToken") as? String ?? singletonclass.instance.getDeviceToken

    let param = [

        "accessToken":accessToken,
        "deviceId":deviceToken,
        "deviceType":"2"
    ]

    for (key,value) in param {

        tempData.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
        tempData.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
        tempData.append("\(value)\r\n".data(using: String.Encoding.utf8)!)

    }
    self.body.append(tempData as Data)
    self.body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
    request.httpBody = self.body as Data

    let session = URLSession.shared

    let task = session.dataTask(with: request as URLRequest) {
        (
        data, response, error) in

        guard let _:NSData = data! as NSData, let _:URLResponse = response, error == nil else { return }
        do
        {
            let responseDict = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [String:Any]
            //print("\n tyiukmqw",responseDict)

            let code = responseDict.value(forKey: "code") as? String
            let message = responseDict.value(forKey: "Message") as? String
            singletonclass.instance.isrofilePicChagedOrNot = false

            if code == "200"
            {
                print("success code")

                DispatchQueue.main.async(execute: {

                    self.userProfile.image = chosenimage
                    UserDefaults.standard.setValue(UIImagePNGRepresentation(chosenimage), forKey: "UserProfilePicture")
                    singletonclass.instance.userProPic = chosenimage

                })
            }
            else
            {
                DispatchQueue.main.async(execute: {

                    singletonclass.instance.showAlert(message!)
                    self.isActivityIndicatorNeed(false)

                })
            }
        }
        catch
        {

        }
    }

    task.resume()
}
Catherine
  • 654
  • 5
  • 15
0

Note : This function is to upload multiple files of different type using Alamofire

// upload file to server
func uploadFiles(files: [Data],completion : @escaping uploadHandler) {

let header : HTTPHeaders = ["Content-Type" : "application/x-www-form-urlencoded"] // if there's Authorization, you may add it in header

let url = URL(string: "Enter the url here")

    Alamofire.upload(multipartFormData: { (multipartFormData) in
        for document in files {
            let fileName = NSUUID().uuidString
            multipartFormData.append(document, withName: "documents", fileName:fileName ,mimeType: "image/jpeg") // You'll have to define the proper mime time for uploading other type of files. You may achieve it by creating a struct and storing the type of each file.
        }
    }, usingThreshold: UInt64.init(), to:url, method: .post, headers: header) { (result) in
        switch result{
        case .success(let upload, _, _):
            upload.responseJSON { response in
                switch response.result {
                case .success(_) : completion(true, nil)
                case .failure(let error) :
                    print("Error in upload: \(error.localizedDescription)")
                    completion(false, nil)
                }
            }
        case .failure(let error):
            print("Error in upload: \(error.localizedDescription)")
            completion(false,error)
        }
    }

}

typealias uploadHandler = (_ status :Bool,_ error :Error?)->()// Define this anywhere globally 

While calling the function I'm passing an array of files, I converted different type of file to data and uploading them to server.

if you want to upload array of images than before calling the function .

var documents = [Data]()
for image in imageArray {
       if let imgData  = UIImageJPEGRepresentation(image, 1.0) {
        documents.append(document)

         }     
       }

Now you can call the upload function and pass the documents and listen to completion Handler.

Good luck .

Tushar Katyal
  • 412
  • 5
  • 12