How to Download File in PHP (Step by Step)

In this tutorial, we will learn how to download file in PHP. Downloading files is one of the most common tasks in web applications. Whether you want to allow users to download images, PDFs, documents, or CSV reports, PHP provides simple and efficient ways to handle file downloads.

When you want to let users download a file from the web server, PHP sends specific HTTP headers to the browser that instruct it to download the file instead of opening or rendering it. To enable file download functionality in PHP, you simply need to set the appropriate HTTP headers and output the file content.

Basic Example for File Download in PHP


Below is a simple PHP script for downloading a file.

<?php
// Define the path to the file you want to offer for download.
$filePath = 'myfile.txt'; // Replace with the actual file path

// Check if the file exists on the server.
if (file_exists($filePath)) {
 // Get the file's basename (e.g., 'myfile.txt')
    $fileName = basename($filePath);

 // Set the appropriate headers for file download.
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream'); // Generic binary file
    header('Content-Disposition: attachment; filename="' . $fileName . '"'); // Force download with specified filename
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($filePath)); // Provide the file size

 // Clear output buffer if necessary
    ob_clean();
    flush();

 // Read the file and output its contents.
    readfile($filePath);
    exit; // Stops further execution after downloading file.
} else {
// Handle the case where the file does not exist.
   echo "Error: File not found.";
}
?>

Explanation:

1. $filePath:

In this example, the variable $filePath stores the path of the file on the server-side you want to make downloadable. In the above example, we have used myfile.txt for downloadable, that exists in the same folder as this PHP script.

2. file_exists() Function:

Then, we have used the file_exists() function, which checks if the specified file really exists on the server before downloading.

3. basename() Function:

The basename() extracts the filename from the full path, which is used for the Content-Disposition header.

4. header() Function:

The header() function sets the HTTP headers that instruct the browser to treat the response as a file download.

5. Content-Description: File Transfer:

This is an HTTP response header which adds a general description about the response. It tells the browser (or client) that the response is a file transfer. It helps the browser understand that the file is intended to be downloaded.

6. Content-Type: application/octet-stream:

This is a generic MIME type that tells the browser the file is binary data. If it is generic, the browser does not try to open the file like a PDF or image. Instead, it prompts the user to download it. If you know the exact type of file, you should use a more specific MIME type. For example:

    • application/pdf → for PDF files
    • image/jpeg → for JPG images
    • text/plain → for text files

7. Content-Disposition: attachment; filename=”…”:

This has two important parts:

  • attachment → It instructs the browser to treat the file as a download rather than trying to open or display it.
  • filename=”example.txt” → It specifies the name of the file the user will see in the Save As dialog when downloading.

Without attachment, many browsers may try to open the file inline. With attachment, the browser forces a download dialog.

8. Expires, Cache-Control, Pragma:

The headers Expires, Cache-Control, and Pragma are mainly used for controlling the cache of files. The purpose of these headers in file downloads makes sure the browser does not cache the file and fetches a fresh copy each time. Here’s what each does:

  • Expires: 0 → It tells the browser that the file has already expired and should not be cached.
  • Cache-Control: must-revalidate → It instructs the browser to re-validate with the server before using any cached version.
  • Pragma: public → This ia a legacy HTTP/1.0 header that also controls caching (mostly for backward compatibility).

Together, these headers ensure the file is always freshly downloaded from the server, not served from the browser cache.

9. Content-Length:

The Content-Length header specifies the size of the file in bytes. This allows the browser to know how big the file is before downloading. For example, the myfile.txt is 2KB, the server sends Content-Length: 2048. The browser can show a progress bar during download.

10. ob_clean() and flush():

These functions are used to clear any existing output buffer and send buffered output to the browser immediately. This can be important to prevent issues with header sending.

11. readfile($filePath):

This function reads the entire file from the server and outputs its content directly to the browser.

12. exit:

This stops the running of script after the file has been sent, preventing any further output.

Example 2: Download a Text File

<?php
$file = "myfile.txt";
if (file_exists($file)) {
   header('Content-Type: text/plain');
   header('Content-Disposition: attachment; filename="' . basename($file) . '"');
   readfile($file);
   exit;
}
?>

When you run this script, the browser will download myfile.txt instead of opening or rendering it.

Example 3: Download a PDF File

<?php
$file = "phptutorial.pdf";
if (file_exists($file)) {
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
?>

Example 3: Download an Image File (JPG/PNG)

<?php
$file = "myimages.jpg";
if (file_exists($file)) {
    header('Content-Type: image/jpeg');
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
?>

When you run this PHP script, the browser will force the image to download instead of displaying it directly on the screen.

Example 6: Secure File Download with Access Check

You should never allow direct file access for security reasons. Therefore, you should check user authentication before allowing download.

<?php
session_start();
if (!isset($_SESSION['loggedin'])) {
    die("Access denied. Please login first.");
}
$file = "private/report.pdf";

if (file_exists($file)) {
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
} else {
    echo "File not found!";
}
?>

Best Practices for File Download in PHP


There are some important points that you should keep in mind before allowing file downloads.

  • Use headers properly.
  • Always check if the file exists before starting the download to avoid errors.
  • Use authentication and authorization to protect sensitive or private files.
  • Set the correct MIME type for better browser compatibility.
  • Use chunked reading for large files to prevent excessive server memory usage.
  • Never expose real file paths. Instead, use PHP scripts to manage and control access securely.