home Tutorial Uploading Large Files in Chunks with Plupload and PHP

Uploading Large Files in Chunks with Plupload and PHP

In this tutorial, we will explore the concept of uploading large files in chunks using the powerful Plupload library and PHP. We’ll delve into the benefits of chunked file uploads compared to single-post uploads and provide step-by-step instructions to implement this efficient and reliable file upload method. Whether you’re a developer or a layman, this comprehensive guide will help you understand and utilize the advantages of chunked file uploads.

Why Upload Big Files in Chunks?

When dealing with large files, such as high-resolution images or lengthy videos, uploading them as a single unit can present several challenges. Here are the key reasons why chunked file uploads are preferred:

  1. Enhanced Performance: Uploading large files in smaller chunks allows for better utilization of network resources. It reduces the chances of timeouts or connection disruptions, resulting in faster and more efficient uploads.
  2. Resumable Uploads: In the event of an interruption or failure during the upload process, chunked uploads enable resuming from where it left off. Users won’t need to start the entire upload again, saving time and bandwidth.
  3. Memory Optimization: Splitting large files into smaller chunks reduces the memory load on both the client and server. This makes it more feasible to handle large file uploads without overwhelming system resources.
  4. Flexibility: Chunked uploads can easily accommodate varying network conditions. They adapt to different connection speeds, allowing files to be uploaded successfully even in environments with low bandwidth or unstable connections.

Step-by-Step Guide to Uploading Large Files in Chunks:

Step 1: HTML Form Setup:

To begin, set up the HTML form that will facilitate the file upload process. Create an HTML file with the following structure:

<form>
<div id="list"></div>
<input type="button" id="pick" value="Upload">
</form>

Include the Plupload library by adding the following script tag to the HTML file:

<script src="https://cdnjs.cloudflare.com/ajax/libs/plupload/3.1.5/plupload.full.min.js"></script>

Step 2: Initialize the Plupload Uploader:

Now, let’s initialize the Plupload uploader in JavaScript to handle the file uploads. Add the following script block to your HTML file:

<script> 
   window.onload = () => {
     var list = document.getElementById("list");

     var uploader = new plupload.Uploader({
        runtimes: "html5",
        browse_button: "pick",
        url: "chunk.php",
        chunk_size: "10mb",
        init: {
          PostInit: () => list.innerHTML = "<div>Ready</div>",
          FilesAdded: (up, files) => {
             plupload.each(files, file => {
             let row = document.createElement("div");
             row.className = "file-row";
             row.id = file.id;
             row.innerHTML = `
                  <div class="file-name">${file.name}</div>
                  <div class="file-size">(${plupload.formatSize(file.size)})</div>
                  <strong></strong>
                 `;
                  list.appendChild(row);
               });
               uploader.start();
            },
            UploadProgress: (up, file) => {
                document.querySelector(`#${file.id} strong`).innerHTML = `${file.percent}%`;
            },
            Error: (up, err) => console.error(err)
         }
     });
     uploader.init();
  };
</script>

This JavaScript code initializes the Plupload uploader with the following configurations:
runtimes specifies the runtime to use (in this case, “html5” for browser-based uploads).
browse_button sets the ID of the button that triggers the file picker.
url specifies the URL of the PHP script that handles the file uploads (chunk.php in this example).
chunk_size determines the size of each chunk (e.g., “10mb” for 10 megabytes).

Additionally, event handlers are set up to handle various stages of the upload process:
PostInit: This event occurs after the uploader has been initialized. It sets the initial state of the upload container.
FilesAdded: This event triggers when files are added to the uploader. It creates a row element for each file and displays the file name and size in the upload container.
UploadProgress: This event is triggered during the upload process and updates the progress percentage for each file in the upload container.
Error: This event handles any errors that occur during the upload and logs them to the console.

Step 3: Handle File Selection:

When files are added to the uploader, we want to display their details in the upload container. Add the following code within the FilesAdded event handler:

let row = document.createElement("div");
row.className = "file-row";
row.id = file.id;
row.innerHTML = `
   <div class="file-name">${file.name}</div>
   <div class="file-size">(${plupload.formatSize(file.size)})</div>
    <strong></strong>
`;
list.appendChild(row);

This code creates a row element for each file and populates it with the file name and size. It then appends the row element to the upload container.

Step 4: Upload Files in Chunks:

To initiate the upload process, we’ll call the uploader.start() method within the FilesAdded event handler. Add the following code within the FilesAdded event handler:

uploader.start();

This code starts the upload process once the files have been added to the uploader.

Step 5: Implement the PHP Script:

Now, let’s implement the PHP script that will handle the server-side processing of the file uploads. Create a new file called chunk.php and copy the following PHP code into it:

<?php
// (a) helper function - server response
function verbose($ok = 1, $info = "")
{
    if ($ok == 0) {
        http_response_code(400);
    }
    exit(json_encode(["ok" => $ok, "info" => $info]));
}

// (b) invalid upload
if (empty($_FILES) || $_FILES["file"]["error"]) {
    verbose(0, "Failed to move uploaded file.");
}

// (c) upload destination - change folder if required!
$filePath = __DIR__ . DIRECTORY_SEPARATOR . "uploads";
if (!file_exists($filePath)) {
    if (!mkdir($filePath, 0777, true)) {
        verbose(0, "Failed to create $filePath");
    }
}
$fileName = isset($_REQUEST["name"])
    ? $_REQUEST["name"]
    : $_FILES["file"]["name"];
$filePath = $filePath . DIRECTORY_SEPARATOR . $fileName;

// (d) deal with chunks
$chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
$chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
$out = @fopen("{$filePath}.part", $chunk == 0 ? "wb" : "ab");
if ($out) {
    $in = @fopen($_FILES["file"]["tmp_name"], "rb");
    if ($in) {
        while ($buff = fread($in, 4096)) {
            fwrite($out, $buff);
        }
    } else {
        verbose(0, "Failed to open input stream");
    }
    @fclose($in);
    @fclose($out);
    @unlink($_FILES["file"]["tmp_name"]);
} else {
    verbose(0, "Failed to open output stream");
}

// (e) check if file has been uploaded
if (!$chunks || $chunk == $chunks - 1) {
    rename("{$filePath}.part", $filePath);
}
verbose(1, "Upload OK");
?>

Let’s break down the important sections of the PHP script:

    1. (a) verbose function: This is a helper function that sends a JSON response with the upload status.
    2. (b) Invalid upload check: This section checks if the uploaded file is valid and handles any errors that may occur.
    3. (c) Upload destination: Specify the folder where the uploaded files will be stored. If the folder doesn’t exist, it will be created.
    4. (d) Dealing with chunks:
      • The script retrieves the chunk number and total number of chunks from the request parameters.
      • It opens an output stream to write the uploaded chunk into a temporary file.
      • If the last chunk is received or it’s a single-chunk upload, the temporary file is renamed to the final file path.
    5. (e) Check if the file has been uploaded: If the last chunk is received or it’s a single-chunk upload, the temporary file is renamed to the final file path.

By following this comprehensive guide, you’ve learned the importance and benefits of uploading large files in chunks using Plupload and PHP. You’ve set up the HTML form, initialized the Plupload uploader, handled file selection, and managed the upload process. Additionally, you’ve implemented a PHP script to handle the server-side processing of the file uploads.

Chunked file uploads offer improved performance, resumable uploads, memory optimization, and flexibility, making them ideal for handling large files effectively. You can now confidently incorporate this technique into your projects, ensuring a seamless user experience when dealing with large file uploads.

Feel free to download the complete HTML file and PHP script for reference:

Remember to customize the PHP script according to your specific requirements, such as adjusting the upload destination folder and adding additional security measures.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.