How to Create a PHP Remote File Downloader with Live Progress Bar

Categories:

Downloading files from a remote server is a common feature for many websites, but adding a live progress bar can take the user experience to the next level. In this tutorial, Iโ€™ll guide you through building a PHP remote file downloader with a real-time progress bar using PHP, AJAX, and JavaScript. Whether youโ€™re a beginner or a seasoned developer, this step-by-step guide will help you create a user-friendly file download system for your WordPress site or any web project.

This tutorial is designed to be practical, with a complete code example hosted on GitHub. By the end, youโ€™ll have a working script thatโ€™s perfect for downloading large files like backups, media, or archives, complete with a sleek progress bar and error handling.

Why Build a PHP File Downloader with a Progress Bar?

Adding a progress bar to your file download system isnโ€™t just about aestheticsโ€”itโ€™s about improving usability and engagement. Hereโ€™s why this project is worth your time:

  • Real-time Feedback: Users see the download progress as it happens, making the process feel transparent and reliable.
  • Error Handling: The script gracefully manages issues like failed connections or permission errors, ensuring a smooth experience.
  • SEO Benefits: User-friendly features like this can boost engagement, reduce bounce rates, and improve your siteโ€™s ranking.
  • Versatility: This script works for various file types and sizes, from small PDFs to large .tar.gz archives.

Prerequisites

Before we dive into the code, make sure you have the following:

  • A web server with PHP 7.4 or higher installed (most WordPress hosting providers support this).
  • Write permissions in the directory where the downloaded files will be saved.
  • Basic knowledge of PHP, HTML, CSS, and JavaScript.
  • A publicly accessible remote file URL for testing (e.g., a .zip, .tar.gz, or media file).
  • A GitHub account to access the code (or you can copy it from the repository linked below).
  • Ensure your server has adequate disk space and PHP is configured with appropriate memory_limit and max_execution_time for large files. The progress bar accuracy depends on the remote server providing Content-Length headers.

Pro Tip: Start with a small test file to verify the script works before tackling large downloads.

The PHP Remote File Downloader Script

The complete code for this project is available on GitHub: PHP Remote File Downloader Repository. This is a single-file solution that combines the frontend (HTML, CSS, JavaScript) and backend (PHP) logic for simplicity. You can download the script, customize it, and integrate it into your WordPress site.

Start download

Hereโ€™s a high-level overview of what the script does:

  • Downloads a remote file to your server while streaming it to the client.
  • Displays a live progress bar that updates in real-time using AJAX and the Fetch API.
  • Provides status messages to confirm success or report errors.
  • Handles large files efficiently with a 4KB buffer and proper memory management.

To use the script, save it as downloader.php in your WordPress theme or plugin directory, ensure your server has write permissions, and access it via a browser. The GitHub repository includes detailed setup instructions.

downloading file

How the Script Works

Letโ€™s break down the key components of this PHP file download script:

  • PHP Backend: The server-side logic uses PHPโ€™s fopen and fread to stream the remote file in 4KB chunks. It saves the file locally and sends the data to the client for progress tracking. The script also extracts the remote fileโ€™s size (via Content-Length headers) to calculate the progress percentage.
  • AJAX with Fetch API: The JavaScript frontend uses the Fetch API to monitor the download stream. It reads the incoming data chunks, calculates the progress, and updates the progress bar and status messages in real-time.
  • Responsive UI: The HTML and CSS create a clean, mobile-friendly interface with a green progress bar, a โ€œStart Downloadโ€ button, and a status display. The design is lightweight and fits seamlessly into any WordPress theme.
  • Error Handling: The script checks for issues like failed connections or missing permissions, displaying user-friendly error messages if something goes wrong.

Note: The progress barโ€™s accuracy depends on the remote server providing Content-Length headers. If these arenโ€™t available, the script will still work, but the percentage wonโ€™t be precise.

Copy below code and paste in PHP file and open PHP file URL

<?php
define('BUFSIZ', 4096);
set_time_limit(0);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $url = 'https://example.com/myfile.zip';
    $output_file = basename($url);

    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $output_file . '"');

    try {
        $remote_file = fopen($url, 'rb');
        if ($remote_file === false) {
            throw new Exception('Failed to open remote file');
        }

        $local_file = fopen($output_file, 'wb');
        if ($local_file === false) {
            fclose($remote_file);
            throw new Exception('Failed to create local file');
        }

        $file_size = 0;
        $remote_headers = stream_get_meta_data($remote_file);
        foreach ($remote_headers['wrapper_data'] as $header) {
            if (stripos($header, 'Content-Length:') === 0) {
                $file_size = (int)trim(substr($header, 15));
                break;
            }
        }

        header('Content-Length: ' . $file_size);

        while (!feof($remote_file)) {
            $buffer = fread($remote_file, BUFSIZ);
            fwrite($local_file, $buffer);
            echo $buffer;
            flush();
        }

        fclose($remote_file);
        fclose($local_file);

    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
    }
    exit;
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Downloader with Progress</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .progress-container { width: 100%; max-width: 600px; margin: 20px 0; }
        .progress-bar { width: 0%; height: 20px; background: #4CAF50; transition: width 0.3s; }
        .progress-wrapper { background: #f0f0f0; border-radius: 5px; overflow: hidden; }
        #status { margin-top: 10px; color: #333; }
        #downloadBtn { padding: 10px 20px; background: #2196F3; color: white; border: none; cursor: pointer; }
        #downloadBtn:disabled { background: #cccccc; cursor: not-allowed; }
    </style>
</head>
<body>
    <h2>Remote File Downloader</h2>
    <button id="downloadBtn" onclick="startDownload()">Start Download</button>
    <div class="progress-container">
        <div class="progress-wrapper">
            <div class="progress-bar" id="progressBar"></div>
        </div>
        <div id="status">Ready to download</div>
    </div>

    <script>
        async function startDownload() {
            const button = document.getElementById('downloadBtn');
            const status = document.getElementById('status');
            const progressBar = document.getElementById('progressBar');
            
            button.disabled = true;
            status.textContent = 'Starting download...';
            
            try {
                const response = await fetch('<?php echo $_SERVER['PHP_SELF']; ?>', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' }
                });
                
                const reader = response.body.getReader();
                const contentLength = +response.headers.get('Content-Length') || 0;
                let receivedLength = 0;
                
                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;
                    
                    receivedLength += value.length;
                    const percentage = contentLength ? 
                        Math.round((receivedLength / contentLength) * 100) : 0;
                    
                    progressBar.style.width = percentage + '%';
                    status.textContent = `Downloading: ${percentage}% (${receivedLength} bytes)`;
                }
                
                status.textContent = 'Download completed successfully!';
                progressBar.style.width = '100%';
                
            } catch (error) {
                status.textContent = 'Error: ' + error.message;
            } finally {
                button.disabled = false;
            }
        }
    </script>
</body>
</html>

Step-by-Step Setup Guide

Follow these steps to implement the PHP remote file downloader on your WordPress site:

  1. Download the Code: Clone or download the script from the GitHub repository.
  2. Customize the URL: In the PHP code, update the $url variable to point to your desired remote file (e.g., https://example.com/myfile.zip).
  3. Upload to WordPress: Place the `down

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *