Image Effects FLV vs WEBM: Which Video Format Should You Choose in 2025? A Beginner’s Guide to Image Comparison in Python Python Image Analysis Tools and Techniques: Where to Start Understanding How to Change the Aspect Ratio of an Image Unleashing the Power of Image Organizers in 2024 How to Make a Low-Quality Image Look Better Understanding Lossless Image Compression How to Set Up Image Registration in Python 8 Different Image Processing Techniques You Can Use 4 Ways to Make an Image Larger without Losing Quality 3 Easy Ways to Eliminate Duplicate Images The Basics of Face Detection in Python How to Implement Multiple File Upload in PHP Like a Pro Creating Custom Image Cropping Interfaces in Android How to Create Simple Yet Effective PHP Overlay Understanding Real-Time Image Recognition How to add a shadow effect to an image with CSS How to crop an image in Flutter with Cloudinary How To Rotate an Image with Java Image Processing with Python Rotating an image with CSS Enhancing User Experience with a Responsive Image Slider Building a Python Image Recognition System Building an Interactive JavaScript Image Manipulation Tool Image Align Centering with HTML and CSS Efficient Image Cropping Techniques with Angular and Cloudinary Ultimate Guide to Photo Gallery on Android A Comprehensive Guide to Adding Text to Images on Android Mastering Background Changes in React Applications Comprehensive Guide on Changing Background on Android Devices Mastering Image Rotation in Java A Guide to Adding Text to Images with Python A Guide to Converting Images to Grayscale with Python Introduction Creating an Image Overlay with JavaScript Rotating an Image in Python Creating a Dynamic Photo Gallery with jQuery Creating An Interactive Photo Gallery Using JavaScript Mastering Overlay in Android Mastering Angular Overlay: A Comprehensive Guide Comprehensive Guide to Overlay in Flutter Mastering Overlay React for Responsive Design Solutions Create a Blurred Image with PHP: A Comprehensive Guide Guide to Using Blur Image in Flutter Mastering Blur Image in React Native Mastering Image Blurring in Python Mastering the Art of Image Blurring Mastering the Art of Image Blurring in Java The Ultimate Guide to Blurring Images on Android Understanding and Implementing Blur Image in JQuery An Extensive Walkthrough of Blurring Images with JavaScript How to Use HTML, CSS, and JavaScript to Make an Image Slider HTML Image Tag How to Crop GIFs? How to Align Images with CSS Ken Burns Effect – Complete Guide and How to Apply It Cartoonify – Complete Guide on Cartoonify Image Effect Mastering Web Aesthetics: A Comprehensive Guide to Gradient Fades Sepia Effect: The Ultimate Guide to the Sepia Photo Effect What is Vignette? Guide to Vignette Image Editing Pixelate – The Ultimate Guide to the Pixelation Effect How to Outline an Image: Enhancing Visual Appeal and Depth Make Your Photos Pop with Image Effects Upscale Image – Developers guide to AI-driven image upscaling Image Manipulation: History, Concepts and a Complete Guide A Full Guide to Object-aware Cropping Simplify Your Life with Automatic Image Tagging How To Resize Images In WordPress How To Create a Progress Bar For Asset Uploads Animated GIFs – What They Are And How To Create Them How To Automatically Improve Image Resolution AI Drop Shadow Get Image Dimensions From URLs Automatically Add Sepia Effect To Images Automatically Make an Image a Cartoon Automatically Add Blur Faces Effect To Images Automatically Add Background Removal Effect to an Image How to Resize an Image with React How to Easily Resize an Image with React Native

How to Implement Multiple File Upload in PHP Like a Pro

Multiple File Upload in PHP

Allowing users the option of multiple file upload in PHP is a common feature in many modern applications today. Simply put, multiple file upload refers to a functionality that allows users to select and upload more than one file at once. In a PHP web application, this is typically done using an HTML input element together with the multiple attribute and the $_FILES variable, which is a superglobal available throughout the scope of the script.

When handling file uploads in an application, you often need a way to store those files—whether in the browser, a database, or a cloud service like Cloudinary. If you’re a PHP developer looking to implement multiple file uploads in your application, you’re in the right place. In this tutorial, we’ll walk you through how to implement multiple file uploads and send the data to Cloudinary for storage. If you’re ready, lets get started!

In this article:

Step 1 – Install Necessary Packages

In your project directory, run the command below to install the required packages for the application:

composer require cloudinary/cloudinary_php vulcas/phpdotenv
  • cloudinary/cloudinary_php: This is the Cloudinary PHP SDK, which allows you to integrate Cloudinary easily with your application. You can use it to effortlessly upload, optimize, transform, upload, and manage your cloud’s assets from within your application.
  • vulcas/phpdotenv: We can load environment variables and other configurations from .env files into our applications.

multiple file upload in php

Step 2 – Set Up the Page Structure

Basically, all we need for the page structure is an HTML form with an input element for the type of file, which indicates that we want to accept only file uploads from the user. After the form is submitted, the data is sent to an upload.php file, which then processes the submitted files and uploads them to Cloudinary.

Create a file named index.html in the project root directory and add the following code to it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Multiple Files Upload</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div class="container">
        <h1>Multiple Files Upload</h1>
        <form action="upload.php" method="post" enctype="multipart/form-data">
            <div class="file-input">
                <input type="file" name="files[]" id="files" multiple>
            </div>
            <ul id="fileList"></ul>
            <button type="submit">Upload Files</button>
        </form>
    </div>
</body>
</html>

In the code above, note the following:

  • The enctype="multipart/form-data" attribute tells the browser to send each file or data field in the form as a separate part of the request.
  • The input element’s type="file" and multiple attributes specify that the browser should accept only file uploads and allow multiple file selections.

Step 3 – Show Selected Files

Presently, there’s no way the user can be sure they selected the correct files they intend to upload. To fix this, we can show a list of the selected files before uploading them using JavaScript.

Before the closing </body> tag in the HTML code above, add the following JavaScript code:

<script>
        function displaySelectedFiles() {
            const fileInput = document.getElementById('files');
            const fileList = document.getElementById('fileList');
            fileList.innerHTML = ''; 

            const files = fileInput.files;

            if (files.length > 0) {
                for (let i = 0; i < files.length; i++) {
                    const listItem = document.createElement('li');
                    listItem.textContent = files[i].name;
                    fileList.appendChild(listItem);
                }
            } else {
                const isEmpty = document.createElement('li');
                isEmpty.textContent = "No files selected.";
                fileList.appendChild(isEmpty);
            }
        }
        document.getElementById('files').addEventListener('change', displaySelectedFiles);
</script>

Step 4 – Add CSS Styles

To style the page, create a file named index.css in the root directory and add the following code to it:

body {
    font-family: Arial, sans-serif;
    background-color: #f5f5f5;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}

.container {
    background-color: white;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    text-align: center;
}

h1 {
    margin-bottom: 20px;
    color: #333;
}

.file-input {
    display: flex;
    justify-content: center;
    align-items: center;
    border: 2px solid #ccc;
    padding: 20px;
    margin-bottom: 20px;
    border-radius: 10px;
    background-color: #f9f9f9;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#files {
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    cursor: pointer;
    transition: border-color 0.3s ease, background-color 0.3s ease;
}

#files:hover {
    border-color: #007bff;
    background-color: #e7f3ff;
}

ul#fileList {
    list-style-type: auto;
    padding: 0;
    margin-top: 10px;
}

ul#fileList li {
    padding: 5px;
    font-size: 14px;
    color: #555;
}

button {
    background-color: #1592df;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s ease;
}

button:hover {
    background-color: #1d4da0;
}

Here’s what the result looks like up to this point:

Multiple Files Upload

Step 5 – Create Environment Variables

It’s always a good practice to store sensitive information such as API keys and secrets in an .env file to avoid unwanted access to it by malicious users. Our Cloudinary credentials are sensitive data so we want to avoid hard-coding them directly into our code.

If you don’t have a Cloudinary account yet, feel free to sign up for a free account and get access to your credentials on the Settings > API Keys in your Cloudinary dashboard.

To do this, create a .env file in the project root and update it as follows:

CLOUDINARY_CLOUD_NAME='<YOUR_CLOUD_NAME>'
CLOUDINARY_API_KEY='YOUR_API_KEY>'
CLOUDINARY_API_SECRET='YOUR_API_SECRET>'

Step 6 – Handle Multiple File Upload in PHP

When the user submits the form, we need to process the files and make sure they uploaded the right type of files before sending them to Cloudinary for storage.

Create a file named upload.php and add the following code to it:

<?php
require 'vendor/autoload.php';

use Cloudinary\Cloudinary;
use Cloudinary\Api\Upload\UploadApi;
use Cloudinary\Configuration\Configuration;
use Dotenv\Dotenv;

// Load the environment variables from .env file
$dotenv = Dotenv::createImmutable(__DIR__); 
$dotenv->load();

// Set up Cloudinary configuration
Configuration::instance([
    'cloud' => [
        'cloud_name' => $_ENV['CLOUDINARY_CLOUD_NAME'],
        'api_key'    => $_ENV['CLOUDINARY_API_KEY'],
        'api_secret' => $_ENV['CLOUDINARY_API_SECRET']
    ],
    'url' => [
        'secure' => true
    ]
]);

$uploadedFiles = [];
$errors = [];

// Check if files were uploaded
if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
        // Check for upload errors
        if ($_FILES['files']['error'][$key] == UPLOAD_ERR_OK) {
            try {
                // Upload the file to Cloudinary
                $uploadResult = (new UploadApi())->upload($tmpName, [
                    'public_id' => pathinfo($_FILES['files']['name'][$key], PATHINFO_FILENAME),
                    'overwrite' => true,
                    'resource_type' => 'image'
                ]);

                $uploadedFiles[] = $uploadResult['secure_url'];
            } catch (Exception $e) {
                $errors[] = "Error uploading " . $_FILES['files']['name'][$key] . ": " . $e->getMessage();
            }
        } else {
            $errors[] = "Error with file " . $_FILES['files']['name'][$key] . ": " . $_FILES['files']['error'][$key];
        }
    }
}
?>

Next, let’s add dynamic HTML to show the results of the file upload and error messages, if any. Still inside the upload.php file, add the code below just below the closing PHP tag:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload Results</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div class="container">
        <h1>Upload Results</h1>
        <?php
        // Display uploaded files
        if (count($uploadedFiles) > 0) {
            echo "<h2>File upload successful:</h2>";
            echo "<ul>";
            foreach ($uploadedFiles as $url) {
                echo "<li><a href='$url' target='_blank'>$url</a></li>";
            }
            echo "</ul>";
        }

        if (count($errors) > 0) {
            echo "<h2>Errors:</h2>";
            echo "<ul>";
            foreach ($errors as $error) {
                echo "<li class='error'>$error</li>";
            }
            echo "</ul>";
        }

        if (count($uploadedFiles) == 0 && count($errors) == 0) {
            echo "<p>No files were selected for upload.</p>";
        }
        ?>
        <a href="index.html"><button>Back to Upload Form</button></a>
    </div>
</body>
</html>

Step 7 – Trying It Out

Now, let’s see the result of our code so far. Select more than one file of your choice, and you should see them listed as shown below:

Multiple Files Upload

Next, click the Upload Files button, then after a brief moment, you should be taken to a page showing the Cloudinary URLs of the uploaded files:

File Upload Successful

Managing Multiple File Upload in PHP

Congratulations if you made it this far! In this article, we covered how to implement multiple file uploads in a PHP application and upload the files to Cloudinary, a cloud-based media asset management solution.

Apart from storing your application data, there’s so much more you can do with Cloudinary. To get started, sign up for a free account today to enjoy the world-class features and flexibility that Cloudinary has to offer.

QUICK TIPS
Colby Fayock
Cloudinary Logo Colby Fayock

In my experience, here are tips that can help you better implement multiple file uploads in PHP:

  1. Optimize file chunking for large files
    Break large files into smaller chunks for upload, using JavaScript on the client side, and reassemble them server-side. This reduces upload failures due to network issues and improves overall performance.
  2. Validate file types client-side and server-side
    Client-side validation using JavaScript is helpful but not foolproof. Always validate file types on the server side as well, using PHP’s mime_content_type() or similar functions to ensure security.
  3. Implement retry logic for failed uploads
    For larger files or less reliable networks, implement a retry mechanism. If an upload fails, allow the client to retry without resubmitting all files, minimizing frustration and server load.
  4. Limit file size and number of files
    Enforce restrictions on file size (php.ini settings like upload_max_filesize and post_max_size) and number of files uploaded in one batch to prevent memory exhaustion and improve server performance.
  5. Use unique file naming conventions
    Avoid overwriting files by appending unique identifiers such as timestamps or UUIDs to filenames. This helps manage files consistently across cloud storage and local environments.
  6. Asynchronous file processing
    Instead of processing uploads synchronously, use background jobs (like RabbitMQ, or PHP workers) for processing large file batches or image transformations. This keeps the user experience smooth and prevents PHP timeouts.
  7. Compress images before upload
    For image-heavy applications, use client-side compression techniques (e.g., the HTML5 Canvas API) before uploading. This reduces bandwidth usage and speeds up the upload process significantly.
  8. Track upload progress using XHR events
    Use JavaScript’s XMLHttpRequest (XHR) to monitor and display the file upload progress in real-time. This provides users with feedback, improving the experience during long uploads.
  9. Leverage Cloudinary transformations
    Use Cloudinary’s image transformations during the upload process to automatically resize or optimize images for web or mobile display, saving storage space and improving load times without additional coding.
  10. Secure uploads with access control
    Ensure that uploaded files are stored in a secure directory with appropriate access controls. Only authorized users should have access to the upload functionality and files, especially sensitive ones.
Last updated: Oct 15, 2024