Upload image with alamofire

I’m trying to upload an image to server with Alamofire but my code doesn’t work. This is my code:

var parameters = ["image": "1.jpg"]
    let image = UIImage(named: "1.jpg")
    let imageData = UIImagePNGRepresentation(image)
    let urlRequest = urlRequestWithComponents("http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/", parameters: parameters, imageData: imageData)
    Alamofire.upload(urlRequest.0, data: urlRequest.1)
        .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
            println("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
        }
        .responseJSON { (request, response, JSON, error) in
            println("REQUEST \(request)")
            println("RESPONSE \(response)")
            println("JSON \(JSON)")
            println("ERROR \(error)")
    }

and this is urlRequestWithComponents methos:

  • iOS8 Beta 3 SpriteKit exc_bad_acces when running on device
  • UITapGestureRecognizer crashes on multiple taps
  • Sorting an array of dictionaries in Swift 2
  • How do I remove a bridge header without getting errors?
  • touchesBegan not called in UIView subclass
  • Unable to activate constraint with anchors
  • func urlRequestWithComponents(urlString:String, parameters:Dictionary<String, String>, imageData:NSData) -> (URLRequestConvertible, NSData) {
    
        // create url request to send
        var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue
        let boundaryConstant = "myRandomBoundary12345";
        let contentType = "multipart/form-data;boundary="+boundaryConstant
        mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")
    
    
    
        // create upload data to send
        let uploadData = NSMutableData()
    
        // add image
        uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData(imageData)
    
        // add parameters
        for (key, value) in parameters {
            uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
        }
        uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
    
    
    
        // return URLRequestConvertible and NSData
        return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData)
    }
    

    and this is what I get in console:

    REQUEST { URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ }
    RESPONSE Optional( { URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ } { status code: 200, headers {
    “Accept-Ranges” = bytes;
    Connection = close;
    “Content-Length” = 345;
    “Content-Type” = “text/html”;
    Date = “Tue, 25 Aug 2015 10:52:01 GMT”;
    “Last-Modified” = “Mon, 24 Aug 2015 03:54:55 GMT”;
    Server = Apache;
    } })
    JSON nil
    ERROR Optional(Error Domain=NSCocoaErrorDomain Code=3840 “The operation couldn’t be completed. (Cocoa error 3840.)” (Invalid value around character 0.) UserInfo=0x7f8c68c1c130 {NSDebugDescription=Invalid value around character 0.})

    my PHP content:

    <? php
    echo $_FILES['image']['name'].
    '<br/>';
    
    
    //ini_set('upload_max_filesize', '10M');
    //ini_set('post_max_size', '10M');
    //ini_set('max_input_time', 300);
    //ini_set('max_execution_time', 300);
    
    
    $target_path = "uploads/";
    
    $target_path = $target_path.basename($_FILES['image']['name']);
    
    try {
      //throw exception if can't move the file
      if (!move_uploaded_file($_FILES['image']['tmp_name'], $target_path)) {
        throw new Exception('Could not move file');
      }
    
      echo "The file ".basename($_FILES['image']['name']).
      " has been uploaded";
    } catch (Exception $e) {
      die('File did not upload: '.$e - > getMessage());
    } ?>

    4 Solutions Collect From Internet About “Upload image with alamofire”

    While Rob’s Answer is correct, here’s the Swift 2.0 version, with upload progress update.

    Just Copy and Paste the following code, change the upload URL, and add in your parameters. Should work like a charm.

    PS: MRProgress is an Awesome Library for progress update!

        let apiToken = "ABCDE"
        Alamofire.upload(
            .POST,
            "http://sample.com/api/upload",
            multipartFormData: { multipartFormData in
                multipartFormData.appendBodyPart(data: imageData, name: "yourParamName", fileName: "imageFileName.jpg", mimeType: "image/jpeg")
                multipartFormData.appendBodyPart(data: apiToken.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"api_token")
                multipartFormData.appendBodyPart(data: otherBodyParamValue.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"otherBodyParamName")
            },
            encodingCompletion: { encodingResult in
                switch encodingResult {
                case .Success(let upload, _, _):
                    upload.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
                        print("Uploading Avatar \(totalBytesWritten) / \(totalBytesExpectedToWrite)")
                        dispatch_async(dispatch_get_main_queue(),{
                            /**
                            *  Update UI Thread about the progress
                            */
                        })
                    }
                    upload.responseJSON { (JSON) in
                        dispatch_async(dispatch_get_main_queue(),{
                            //Show Alert in UI
                            print("Avatar uploaded");
                        })
                    }
    
                case .Failure(let encodingError):
                    //Show Alert in UI
                    print("Avatar uploaded");
                }
            }
        );
    

    Your error is telling you that the response is not valid JSON. You’re calling responseJSON, indicating that you’re expecting JSON response, but your server code isn’t generating JSON. So there are two solutions:

    1. I’d suggest changing your PHP code to generate JSON responses.

      For example, if successful:

      echo json_encode(array("success"    => true,
                             "filename"   => basename($_FILES['image']['name']));
      

      or, if not successful, perhaps:

      echo json_encode(array("success"    => false,
                             "error_code" => 42,
                             "error_msg"  => 'File did not upload: '.$e - > getMessage());
      

      Clearly, you have to remove the extraneous echo lines in the PHP if you’re going to return JSON, but hopefully this illustrates the pattern. But this will generate a response that you can parse with Alamofire’s responseJSON (or use NSJSONSerialization).

    2. Alternatively, you could change the Alamofire code to not expect JSON (e.g. call response rather than responseJSON), but then parsing the responses becomes far more difficult.

    As a minor, unrelated issue, I’d personally advise not building that request manually, but rather let Alamofire do that for you. Here’s an example from the README:

    Alamofire.upload(
        multipartFormData: { multipartFormData in
            multipartFormData.append(unicornImageURL, withName: "unicorn")
            multipartFormData.append(rainbowImageURL, withName: "rainbow")
        },
        to: "https://httpbin.org/post",
        encodingCompletion: { encodingResult in
            switch encodingResult {
            case .success(let upload, _, _):
                upload.responseJSON { response in
                    debugPrint(response)
                }
            case .failure(let encodingError):
                print(encodingError)
            }
        }
    )
    

    This is for Swift 3 and Alamofire 4. See revision history for this question for prior versions.

    SWIFT 2 AlamoFire total Solution for image upload to REST API

    AlamoFire contain load of simplified solution. Alamofire.request method contains several simplified overload which can use to upload in simple manner. By using Alamofire.request( method developer can get rid of encoding overhead.

    Please check my solution below.

    The solution was Tested on SWIFT 2.0

    import UIKit
    import Alamofire
    
    class ViewController: UIViewController {
    
        @IBOutlet var imageView: UIImageView!
        @IBOutlet var btnUpload: UIButton!
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        func successDataHandler(responseData:String){
    
            print ("IMAGE UPLOAD SUCCESSFUL    !!!")
    
        }
    
        func failureDataHandler(errorData:String){
    
            print ("  !!!   IMAGE UPLOAD FAILURE   !!! ")
    
        }
    
        @IBAction func actionUpload(sender: AnyObject) {
    
            let URL = "http://m8coreapibeta.azurewebsites.net/api/cards/SaveImages"
    
            let postDataProlife:[String:AnyObject] = ["CardId":(dataCardDetail?.userId)!,"ImageType":1,"ImageData":imageView.image!]
    
            uplaodImageData(URL, postData: postDataProlife, successHandler: successDataHandler, failureHandler: failureDataHandler)
        }
    
        func uplaodImageData(RequestURL: String,postData:[String:AnyObject]?,successHandler: (String) -> (),failureHandler: (String) -> ()) -> () {
    
            let headerData:[String : String] = ["Content-Type":"application/json"]
    
            Alamofire.request(.POST,RequestURL, parameters: postData, encoding: .URLEncodedInURL, headers: headerData).responseString{ response in
                switch response.result {
                case .Success:
                    print(response.response?.statusCode)
                    successHandler(response.result.value!)
                case .Failure(let error):
                    failureHandler("\(error)")
                }
            }
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    
    }
    
    let parameters: Parameters = [
          "userid":user.userID!
        ]
    
        print("the uploadData - \(parameters)")
    
        let imageData = UIImageJPEGRepresentation(deviceImage.image!, 1)
    
        let url = try! URLRequest(url: URL(string:"your URL here")!, method: .post, headers: nil)
    
        Alamofire.upload(multipartFormData: { (multipartFormData) in
          multipartFormData.append(imageData!, withName: "file_name", fileName: "abc.jpg", mimeType: "image/jpg")
          for (key, value) in parameters {
            multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
          }
        }, with: url, encodingCompletion: { (result) in
                switch result {
    
                case .success(let upload, _, _):
    
                  upload.responseJSON { response in
    
                    if response.response?.statusCode == 200 {
                      PrepareUIElements.showAlertAndPerformSegue(sender: self, message: "Uploaded Successfully", identifier: "ShowHome")
                    } else {
                      print("whatever you want")
                    }
                  }
    
                case .failure(let encodingError):
                  PrepareUIElements.showAlert(sender: self, message: "Unable to Upload")
                  print(encodingError)
                }
    
        })