How to Download a File in PHP

This short tutorial will help you to learn how to download a file with PHP.

Just follow the examples below to easily meet that goal.

Using the readfile() Function

If you want to make different types of files or images load the files directly into the drive of the user with PHP, you can run the readfile() function.

Watch a course Learn object oriented PHP

Let’s see how to do it on the example of creating an image gallery, which will help the users to download image files using just one click.

In the example below, an image-gallery.php is generated and a code is placed inside it:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Simple Image Gallery</title>
    <style>
      .img-box {
        display: inline-block;
        text-align: center;
        margin: 0 15px;
      }
    </style>
  </head>
  <body>
    <?php
    // Array encompassing sample image file names
    $images = ["kites.jpg", "balloons.jpg"];

    // Looping through the array to generate an image gallery
    foreach ($images as $image) {
        echo '<div class="img-box">';
        echo '<img src="images/' . $image . '" width="200" alt="' . pathinfo($image, PATHINFO_FILENAME) . '">';
        echo '<p><a href="download.php?file=' . urlencode($image) . '">Download</a></p>';
        echo '</div>';
    }
    ?>

  </body>
</html>

So, in the example above, the download link points to the download.php file. The URL, on its turn, encompasses an image file name, just as a query string. Also, you can notice, that the urlencode() function is applied for encoding the image file names in a way that they may be safely passed like a URL parameter. The reason is that file names may include unsafe URL characters. The entire code of the download.php, forcing image download looks as follows:

<?php

if (isset($_REQUEST["file"])) {
  // Get parameters
  $file = urldecode($_REQUEST["file"]); // Decode URL-encoded string

  /* Check if the file name includes illegal characters
   like "../" using the regular expression */
  if (preg_match('/^[^.][-a-z0-9_.]+[a-z]$/i', $file)) {
    $filepath = "images/" . $file;

    // Process download
    if (file_exists($filepath)) {
      header('Content-Description: File Transfer');
      header('Content-Type: application/octet-stream');
      header('Content-Disposition: attachment; filename="' . basename($filepath) . '"');
      header('Expires: 0');
      header('Cache-Control: must-revalidate');
      header('Pragma: public');
      header('Content-Length: ' . filesize($filepath));
      flush(); // Flush system output buffer
      readfile($filepath);
      die();
    } else {
      http_response_code(404);
      die();
    }
  } else {
    die("Invalid file name!");
  }
}

?>

Other file formats such as pdf, doc, and so on, can also be downloaded in the way, demonstrated above.

It is crucial to consider that in the example above, the regular expression (line 8) doesn’t allow files with the names that start or end with a dot (.). For example, you can use filenames such as books.jpg or Books.jpg but can’t use books.jpg., .kites.jpg, and so on.