'Swift Upload Multi Images to PHP Server

I want to upload multiple images to my server using Alamofire Lib, but it's uploading 1 image only.

I'm using an image picker that returns an array of UIImage which is Named

imagesdata

This is my code:

@IBAction func uploadimages(_ sender: Any) {
    Alamofire.upload(
        multipartFormData: { multipartFormData in
            for img in self.imagesdata{
            let imgdata = UIImageJPEGRepresentation(img, 1.0)
                multipartFormData.append(imgdata!,withName: "image", fileName: "image.jpg", mimeType: "image/jpeg")
                print("$$$$$$$$$$   :  \(imgdata!)")
            }
        },
        to: "http://localhost/maarathtest/MAPI/img_upload.php",
        encodingCompletion: { encodingResult in
            switch encodingResult {
            case .success(let upload, _, _):
                upload.responseJSON { response in
                    debugPrint(response)
                }
            case .failure(let encodingError):
                print(encodingError)
            }
    }
    )
}

and my PHP:

<?php

$response = array();
if (empty($_FILES["image"])) {
    $response['File'] = "NOFILE";;
} else {
    $filename = uniqid() . ".jpg";
    // If the server can move the temporary uploaded file to the server
    if (move_uploaded_file($_FILES['image']['tmp_name'], "images/" . $filename)) {
        
        $response['status'] = "Success";
        $response['filepath'] = "https://serverName/MAPI/images/" . $filename;
} else {
    $response['status'] = "Failure";
  }
}

echo json_encode($response);
?>

And my console log:

$$$$$$$$$$   :  5849743 bytes
$$$$$$$$$$   :  3253337 bytes
[Request]: POST http://localhost/maarathtest/MAPI/img_upload.php
[Response]: <NSHTTPURLResponse: 0x600000620940> { URL: http://localhost/maarathtest/MAPI/img_upload.php } { status code: 200, headers {
    Connection = "Keep-Alive";
    "Content-Length" = 101;
    "Content-Type" = "text/html";
    Date = "Thu, 25 May 2017 10:08:08 GMT";
    "Keep-Alive" = "timeout=5, max=100";
    Server = "Apache/2.4.18 (Unix) OpenSSL/1.0.2h PHP/5.5.35 mod_perl/2.0.8-dev Perl/v5.16.3";
    "X-Powered-By" = "PHP/5.5.35";
} }
[Data]: 101 bytes
[Result]: SUCCESS: {
    filepath = "https://serverName/MAPI/images/5926ad083b770.jpg";
    status = Success;
}

I have changed my code as below,

 Alamofire.upload(
            multipartFormData: { multipartFormData in
                var count = 1
                for img in self.imagesdata{
                let imgdata = UIImageJPEGRepresentation(img, 1.0)
                multipartFormData.append(imgdata!,withName: "image\(count)", fileName: "image\(count).jpg", mimeType: "image/jpeg")
                count += 1
        }
        },...
<?php

$response = array();
if (empty($_FILES["image1"])) {
    $response['File1'] = "NOFILE";
} else {
    $filename = uniqid() . ".jpg";
    // If the server can move the temporary uploaded file to the server
    if (move_uploaded_file($_FILES['image1']['tmp_name'], "images/" . $filename)) {
        
        $response['status1'] = "Success";
        $response['filepath1'] = "https://serverName/MAPI/images/" . $filename;
} else {
    $response['status1'] = "Failure";
  }
}

if (empty($_FILES["image2"])) {
    $response['File2'] = "NOFILE";
} else {
    $filename = uniqid() . ".jpg";
    // If the server can move the temporary uploaded file to the server
    if (move_uploaded_file($_FILES['image2']['tmp_name'], "images/" . $filename)) {
        
        $response['status2'] = "Success";
        $response['filepath2'] = "https://serverName/MAPI/images/" . $filename;
} else {
    $response['status2'] = "Failure";
  }
}

echo json_encode($response);
?>

Now it's uploading the images, but I don't think this is the proper way to do it, since I don't know how many images users want to upload!

How can I do this properly?



Solution 1:[1]

I have solved the issue, the code below hope to help some 1

Swift :

 @IBAction func uploadimages(_ sender: Any) {


        Alamofire.upload(
            multipartFormData: { multipartFormData in
                var count = 1
                for img in self.imagesdata{
                let imgdata = UIImageJPEGRepresentation(img, 0.5)
                    // the name should be as array other wise want work
                multipartFormData.append(imgdata!,withName: "image[]", fileName: "image\(count).jpg", mimeType: "image/jpeg")
                count += 1

        }

        },
            to: "http://localhost/maarathtest/MAPI/img_upload.php",

            encodingCompletion: { encodingResult in
                switch encodingResult {
                case .success(let upload, _, _):
                    upload.responseJSON { response in
                        debugPrint(response)
                    }
                case .failure(let encodingError):
                    print(encodingError)
                }
        }
        )

    }

PHP code sample :

<?php


$response = array();
if (empty($_FILES["image"])) {

    $response['File1'] = "NOFILE";

}else {

    //$filename = uniqid() . ".jpg";

    // loop through files array from IOS app 
    foreach ($_FILES["image"]["tmp_name"] as $index => $tmp_name) {
    $filePath = "images/" . basename($_FILES["image"]["name"][$index]);
    if (move_uploaded_file($tmp_name, $filePath)) {

        // Images are stored in file path , do what ever is needed 

        $response['filepath'][$index] = $filePath;
    }
           $response['status'] = "Success";

}

}

echo json_encode($response);
?>

Solution 2:[2]

Use this below code to upload multiple images to your server. I've put this in a method that takes in NSMutableArray of UIImage objects and their corresponding names in another array. You could change NSMutableArray to Swift Array if you want. After successful upload, the completion handler will get called and would return a mapped object based on your response:

Code:

public func executeMultipleImageUpload<T: Mappable>(type: T.Type, url: String, parameters: Dictionary<String, String>, images: NSMutableArray?, names: [String], view: UIView, completion: @escaping(_ result: DataResponse<T>?)-> Void) {

    //Calling Alamofire Upload method here...

    Alamofire.upload(multipartFormData: { multipartFormData in // This is first param, the part data itself

        if images == nil || images?.count == 0 {

            print("There are no images to upload..!!")

        } else {

            //Append image data from array of images to multipart form data

            var count = 1
            for image in images! {

                if let imageData = UIImageJPEGRepresentation(image as! UIImage, 0.76) {

                    multipartFormData.append(imageData, withName: names[count - 1], fileName: names[count - 1], mimeType: "image/jpeg")
                }

                count += 1

            }

        }

        //We are encoding the parameters to be sent here in the multipart as well..

        for (key, value) in parameters {

            multipartFormData.append((value.data(using: .utf8))!, withName: key)

        }}, to: url, method: .post, headers: ["": ""], //This is second param (to:)
        encodingCompletion: { encodingResult in // This is third param (encodingCompletion:)

            switch encodingResult {

            case .success(let upload, _, _):

                upload.response { [weak self] response in

                    guard self != nil else {

                        return
                    }

                    debugPrint(response)

                    }.validate().responseObject{

                        (response: DataResponse<T>) in

                            completion(response)


                }

            case .failure(let encodingError):

                print("error:\(encodingError)")

            }

    })

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mohammed Riyadh
Solution 2 badhanganesh