0

i need to save an image on my server i have tried the following:

func saveImageOnServer(_ image: UIImage) {
    let fileid:String = files id here
    let parameters : NSMutableDictionary? = [
        "fileId": fileid]


    let filename:String = filename here

    let url = url here
    let afHTTP : AFHTTPRequestSerializer = AFHTTPRequestSerializer()
    let request: NSMutableURLRequest = afHTTP.multipartFormRequest(withMethod: "POST", urlString: url, parameters: parameters as? [String : Any], constructingBodyWith: {(formData: AFMultipartFormData) in

        let imageData = UIImageJPEGRepresentation(image as UIImage, 0.5)!
        formData.appendPart(withFileData: imageData, name: "uploaded_file", fileName: filename, mimeType: "image/*")
    }, error: nil)
    let manager  = AFURLSessionManager()
    let uploadTask:URLSessionUploadTask = manager.uploadTask(withStreamedRequest: request as URLRequest, progress: nil, completionHandler: { (response, responseObject, error) in
        print(responseObject as Any)
    })
    uploadTask.resume()
}

but for some reason the responseObject is always returning nil no matter what i change in my PHP code even if i have something as simple as the following:

public function uploadColoringImage () {
        return "1";
}

any help will be much appreciated!

user3411226
  • 183
  • 1
  • 14
  • Why aren't you using [Alamofire](https://github.com/Alamofire/Alamofire) instead of AFNetworking? – Alejandro Iván Mar 16 '18 at 15:28
  • i have used it in my whole App and it works just fine , but i never had to upload an image before:) still can't figure out the problem! – user3411226 Mar 16 '18 at 16:12
  • Check [this answer](https://stackoverflow.com/a/36710218/1986221), they use `AFHTTPRequestOperationManager`, it may be useful (yes, that's in Objective-C, but it can help you understand what you're doing wrong). – Alejandro Iván Mar 16 '18 at 16:18

2 Answers2

0

The easiest way to upload image to your API server is to convert it into base64 string:

let image: UIImage = UIImage(named:"myImage")!
let imageData: Data = UIImageJPEGRepresentation(image, 1.0)!

let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)

Then just set that strBase64 as POST or PUT parameter and shoot request and then decode base64 into jpeg in your backend like that:

https://stackoverflow.com/a/17811089/5765283

Bio-Matic
  • 793
  • 1
  • 8
  • 20
  • This is Swift, use `Data`, not `NSData`. – rmaddy Mar 16 '18 at 15:52
  • I think it does not has big difference, this code is just a pseudocode explanation. This is not a school, this is stackoverflow. – Bio-Matic Mar 16 '18 at 16:41
  • 1
    Right. This is Stack Overflow where answers are meant to be useful which means the answers should be correct and use proper code and proper classes. Half of the questions posted here are the result of someone copying and pasting bad code. No need to contribute to the issue. `NSData` is for Objective-C, `Data` is for Swift. So yes, big difference. – rmaddy Mar 16 '18 at 16:45
0

This worked fine for me hope it helps:

func createBodyWithParams(parameters: [String : String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {

    let body = NSMutableData();

    if parameters != nil {
        for (key, value) in parameters! {
            body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
            body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
            body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
        }
    }

   let filename = filename here

    let mimetype = "image/*"

    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
    body.append(imageDataKey as Data)
    body.append("\r\n".data(using: String.Encoding.utf8)!)

    body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)

    return body
}


// upload image to server
func saveImageOnServer(_ image: UIImage) {
    let fileid:String = "\(jsonData["categories"][selectedCategoryIndex]["images"][selectedImageIndex]["fileid"].stringValue)"
    print(jsonData)
    let param : NSMutableDictionary? = [
        "fileId": fileid]

    let address = URL(string: "URL here")!
    var request = URLRequest(url: address)
    request.httpMethod = "POST"


    let boundary = "Boundary-\(NSUUID().uuidString)"

    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    let imageData = UIImagePNGRepresentation(image)

    if imageData == nil {
        return
    }

    request.httpBody = createBodyWithParams(parameters: (param as! [String : String]), filePathKey: "uploaded_file", imageDataKey: imageData! as NSData, boundary: boundary) as Data

    // launch session
    let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in

        // get main queue to communicate back to user
        DispatchQueue.main.async {
            print(response)
            if error == nil {

                do {

                    let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
                    print(json)
                    guard let parseJSON = json else {

                        print("error while parsing")
                        return

                    }

                    print(parseJSON)

                } catch {

                    print("Caught an error: \(error)")

                }

            } else {

                print(error)

            }
        }
    })

    task.resume()

}
user3411226
  • 183
  • 1
  • 14