How to upload multiple images in multipart using Alamofire?

10,702

Solution 1

In Swift 3 and above Just append "[]" with image key identifier to treat it as array of images.

Alamofire.upload(multipartFormData: { multipartFormData in
            // import image to request
            for imageData in imagesData {
                multipartFormData.append(imageData, withName: "\(imageParamName)[]", fileName: "\(Date().timeIntervalSince1970).jpeg", mimeType: "image/jpeg")
            }
            for (key, value) in parameters {
                multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
            }
        }, to: urlString,

            encodingCompletion: { encodingResult in
                switch encodingResult {
                case .success(let upload, _, _):
                    upload.responseJSON { response in

                    }
                case .failure(let error):
                    print(error)
                }

        })

Solution 2

I Hope it will be helpful for you:

Using Swift 3x: (I have uploaded four Photos in this snippet)

 //MARK: - upload multiple photos

    func uploadImagesAndData(params:[String : AnyObject]?,image1: UIImage,image2: UIImage,image3: UIImage,image4: UIImage,headers : [String : String]?, completionHandler:@escaping CompletionHandler) -> Void {

        let imageData1 = UIImageJPEGRepresentation(image1, 0.5)!
        let imageData2 = UIImageJPEGRepresentation(image2, 0.5)!

        let imageData3 = UIImageJPEGRepresentation(image3, 0.5)!

        let imageData4 = UIImageJPEGRepresentation(image4, 0.5)!


        Alamofire.upload(multipartFormData: { multipartFormData in

                for (key, value) in params! {
                    if let data = value.data(using: String.Encoding.utf8.rawValue) {
                        multipartFormData.append(data, withName: key)
                    }
                }

                multipartFormData.append(imageData1, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
                multipartFormData.append(imageData2, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
                multipartFormData.append(imageData3, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
                multipartFormData.append(imageData4, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")

        },
            to: K_BASEURL + K_API_LOGINDATA, encodingCompletion: { encodingResult in
                switch encodingResult {
                case .success(let upload, _, _):
                    upload
                        .validate()
                        .responseJSON { response in
                            switch response.result {
                            case .success(let value):
                                print("responseObject: \(value)")
                            case .failure(let responseError):
                                print("responseError: \(responseError)")
                            }
                    }
                case .failure(let encodingError):
                    print("encodingError: \(encodingError)")
                }
        })
    }

Solution 3

1) To upload multiple image using Alamofire in Swift3

typealias APICompletionHandler = (code:Int, error:NSError?, response:AnyObject?) -> Void

func uploadIMultipart(_ strApiName:String, param : NSDictionary?, data:Array<NSDictionary>, header:[String : String]?, completionHandler:@escaping APICompletionHandler)
    {
        let strURL : String = strApiName

        let apiURL = try! URLRequest(url: strURL, method: .post, headers: header)

        Alamofire.upload(multipartFormData: { (multipartFormData) in
            // code
            var i : Int = 0
            for dict:NSDictionary in data {
                let extention = dict["format"] as? String
                let strMimeType = dict["strMimeType"] as? String
                let nameofFile:String = (6.randomString as String)+"."+extention!
                if (dict["data"] as? Data != nil) {
                    multipartFormData.append(Foundation.Data(dict["data"] as! Data), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)
                } else {
                    let strUrl = dict["data"] as! String
                    let fileURL : URL? = URL(string: strUrl)
                    multipartFormData.append(try! Foundation.Data(contentsOf: fileURL!), withName: dict["key"] as! String, fileName: nameofFile , mimeType: strMimeType!)

                }
                i += 1
            }

            for (key, value) in param! {
                multipartFormData.append((value as! NSString).data(using: String.Encoding.utf8.rawValue)!, withName: key as! String)
            }

        }, with: apiURL, encodingCompletion: { (result) in
            // code
            switch result {

            case .success(let upload,_ ,_ ):
                upload.responseJSON { response in

                    switch response.result {
                    case .success(let data):
                        //Sucess
                    case .failure(let error):
                        print(error.localizedDescription)

                    }
                }
            case .failure(let encodingError):
                print(encodingError)
                completionHandler(0, encodingError as NSError?, nil)
            }
        })
    }

2) To call Function

        let imageData : NSData = UIImagePNGRepresentation(imgUserProfile.image!)! as NSData
        let imageData1 : NSData = UIImagePNGRepresentation(imgUserProfile.image!)! as NSData

        let dict1: Dictionary = ["data":imageData,"key":"user_image", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
        let dict2: Dictionary = ["data":imageData1,"key":"image1", "format":"jpg", "strMimeType":"image/jpeg"] as [String : Any]
        let array: Array = [dict1,dict2]; //pass this image array

        self.uploadIMultipart(strAPI, param: dictParam as NSDictionary, data: array as Array<NSDictionary>, header: nil) { (code, error, response) in
            AppSingletonObj.stopLoading(inView: self.view)

            //API manager sucess or failure
            if code == 1 {
                let status = response?["success"]

                //API sucess or failure
                if(status as! Int == 1) {
                    print(response!)
                }
                else {
                    let errorMessage = response?["message"]
                    AppSingletonObj.showAlert(msg: errorMessage as! String)
                }
            }
            else {
                AppSingletonObj.showAlert(msg: "Some error occured! please try after sometime")
            }
        }

3) Extension to create file name

//MARK: CREATE RANDOM STRING of LENGTH
extension Int{
    var randomString : String {

        let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let randomString : NSMutableString = NSMutableString(capacity: self)

        for _ in 0 ..< self{
            let length = UInt32 (letters.length)
            let rand = arc4random_uniform(length)
            randomString.appendFormat("%C", letters.character(at: Int(rand)))
        }
        return randomString as String
    }
}
Share:
10,702

Related videos on Youtube

Nakul Sharma
Author by

Nakul Sharma

Highly dedicated and devoted to work for achieving the proposed and desired goal. I ever excel myself by learning every thing which comes in my way, which helps me to work in a challenging environment. A self learned iOS developer plus Team Lead and a coder by passion. I have 5.4 years experience as iOS developer:- iOS applications developed using Swift and objective-C. Requirement Analysis &amp; gathering. App Development,Bug fixing and maintenance. Proficient with Apple Store app upload process. Proficient with XCode IDE and iOS SDK. Social networking sites (Facebook, GooglePlus and LinkedIn) integration. Having knowledge of Cocoa Touch,UIKit, Interface builder, Core Data, and APNS. Having knowledge of XML and JSON parsing.Instant Chat with XAMPP and Openfire. Able to use third party Libraries like Parse, Branch,Facebook,Google.My Own Frameworks and Third Party controls. (I will post soon on cocoa control)

Updated on June 04, 2022

Comments

  • Nakul Sharma
    Nakul Sharma almost 2 years

    I am stuck in uploading multiple images in multipart using Alamofire. Can any one help me? Thanks in advance!!

    For more details, I am using this code to create body part of images data:

    func imageArrayToNSData(array: [UIImage],boundary:String) -> NSData {
        let body = NSMutableData()
        var i = 0;
        for image in array{
            let filename = "image\(i).jpg"
            let data = UIImageJPEGRepresentation(image,0.8);
            let mimetype = "image/jpeg"
            let key = "product_images"
            body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            body.appendData("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            body.appendData("Content-Type: \(mimetype)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            body.appendData(data!)
            body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            i += 1
        }
    
        body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        return body
    }
    

    to upload I am using :

            Alamofire.upload(.POST, EDIT_PRODUCT_URL, headers: ["Accept": "application/json","Content-Type":"application/json"], multipartFormData: { (formData) in
    
            if productImages.count>0{
                let boundary = generateBoundaryString()
                let imageData = CommonClass.imageArrayToNSData(productImages,boundary: boundary)
                formData.appendBodyPart(data: imageData, name: "product_images", mimeType: "image/jpeg")
            }
    
            for (key, value) in params {
                if value is [String]{
                    let data = CommonClass.stringArrayToNSData(value as! [String])
                    formData.appendBodyPart(data:data , name: key)
                }else if value is String{
                    formData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
                }else if let v = value as? Bool{
                    var bValue = v
                    let d = NSData(bytes: &bValue, length: sizeof(Bool))
                    formData.appendBodyPart(data: d, name: key)
                }
            }
    
        }) { (encodingResult) in
            switch encodingResult {
            case .Success(let upload, _, _):
                KVNProgress.showProgress(CGFloat(0), status:"0% Sent")
                upload.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
                    // This closure is NOT called on the main queue for performance
                    // reasons. To update your ui, dispatch to the main queue.
                    dispatch_async(dispatch_get_main_queue()) {
                        let prg = Int((CGFloat(totalBytesWritten)*100)/CGFloat(totalBytesExpectedToWrite))
                        if prg == 100{
                            KVNProgress.showSuccessWithStatus("Created")
                        }
                        KVNProgress.updateStatus("\(prg)% Sent")
                        KVNProgress.updateProgress(CGFloat(Float(prg)/100.0), animated: true)
                    }
                }
                upload.responseJSON { response in
                    CommonClass.hideLoader()
                    switch response.result {
                    case .Success:
                        if let value = response.result.value {
                            let json = JSON(value)
                            print_debug("edit Product JSON is\n\(json)");  
                            completionBlock(json)
                        }else{
                            completionBlock(nil)
                        }
                    case .Failure(let error):
                        print_debug(error.description)
                        showErrorWithMessage("Oops! Couldn't connect to server!")
                        completionBlock(nil)
                    }
                }
    
            case .Failure(let encodingError):
                print(encodingError)
            }
        }
    

    Can any one please let me suggest the way to upload multiple files in multipart using Alamofire?

  • Nakul Sharma
    Nakul Sharma over 7 years
    Let me check @Rajat, If it solve, I will surely do the else work :)
  • deeJ
    deeJ over 6 years
    "withName" parameter has to be different for every new append. Otherwise they will just get overwritten.
  • Anurag Sharma
    Anurag Sharma over 6 years
    No, "fileName" is responsible for that! and "withName" is to be a "file" because this is just to specify the type.
  • Himanshu Parashar
    Himanshu Parashar almost 6 years
    @AnuragSharma can you tell me the code if we have to send images in separate array?
  • Hardik Thakkar
    Hardik Thakkar over 4 years
    Extra parameters which will be pass in API.