Force download a file using PHP

A force-download script can give you more control over a file download than you would have providing a direct link that may be the good thing for most of the time to read it online. But sometimes it can be very frustrating to click on a link to a document you want people to read, and then have to wait for it to download and finally open on your computer that may not have the right program to open it.

But what if you have a file and you want people to download it with save as option? If it is an HTML file or a PDF file or an image file or a video file, you cannot just post link, as the web browsers open those automatically; instead you need to do some tricky thing using PHP programming language.

PHP allows you to change the HTTP headers of files that you are writing, so that you can force a file to be downloaded instead of displaying the content on the browser that normally the browser would load in the same window.

This is perfect for files like PDFs, document files, images, and videos that you want your customers to download rather than read online.

Prerequisites

PHP 7.4.3, Apace http Server 2.4

Project Directory

It’s assumed that you have setup Apache and PHP in Windows system.

Now we will create a project root directory called php-force-download-file under the Apache server’s htdocs folder.

I may not mention the project root directory in subsequent sections and I will assume that I am talking with respect to the project root directory.

File Download Script

Create a common.php file with below source code.

You can check the tutorial How to get mime type of a file using PHP for mime types of the files.

Here I am downloading the file from the project’s root directory but ideally you should have some kind of download path for the file, may be it is an external service or a physical location of the disk or a database table, etc.

<?php

//force file download
function force_download($filename = '') {

    if ($filename == '') {
        return FALSE;
    }

    // Try to determine if the filename includes a file extension.
    // We need it in order to set the MIME type
    if (FALSE === strpos($filename, '.')) {
        return FALSE;
    }

    $data = file_get_contents($path . $filename);

    // Grab the file extension
    $x = explode('.', $filename);
    $extension = end($x);

    // Set a default mime if we can't find it
    if (!isset($mimes[$extension])) {
        $mime = 'application/octet-stream';
    } else {
        $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
    }

    // Generate the server headers
    if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE) {
        header('Content-Type: "' . $mime . '"');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header("Content-Transfer-Encoding: binary");
        header('Pragma: public');
        header("Content-Length: " . strlen($data));
    } else {
        header('Content-Type: "' . $mime . '"');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header("Content-Transfer-Encoding: binary");
        header('Expires: 0');
        header('Pragma: no-cache');
        header("Content-Length: " . strlen($data));
    }

    exit($data);
    
}

Download Button

Ceate a PHP web page php-force-download-file.php with the following source code. IT display the download button to the end users and they need to click on it to download the file. Here I am going to download the file pclzip.lib.php which is kept under project’s root directory.

<?php
require_once 'common.php';

if (isset($_POST['download'])) {
    force_download('pclzip.lib.php');
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
            <h3>Force Download File</h3>
            <div>
                <input type="submit" name="download" value="Download"/>
            </div>
        </form>
    </body>
</html>

Testing the Application

So we are done with the coding part, now let’s test our application.

You can hit the URL http://localhost/php-force-download-file/php-force-download-file.php in the browser.

Clicking on the Download button will give you the file opened in new window for “Open with” or “Save” options.

force download file php

That’s all about forcing a file download using PHP language.

Source Code

Download

Thanks for reading.

Leave a Reply

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