Forcing to download a file using PHP

2018-12-31 06:06发布

I have a CSV file on my server. If a user clicks on a link it should download, but instead it opens up in my browser window.

My code looks as follows

<a href="files/csv/example/example.csv">
    Click here to download an example of the "CSV" file
</a>

It's a normal webserver where I have all of my development work on.

I tried something like:

<a href="files/csv/example/csv.php">
    Click here to download an example of the "CSV" file
</a>

Now the contents of my csv.php file:

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=example.csv');
header('Pragma: no-cache');

Now my issue is it's downloading, but not my CSV file. It creates a new file.

10条回答
人间绝色
2楼-- · 2018-12-31 07:02

To force download you may use Content-Type: application/force-download header, which is supported by most browsers:

function downloadFile($filePath)
{
    header('Content-Type: application/force-download');
    header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
    header('Content-Length: ' . filesize($filePath));
    readfile($filePath);
}

A BETTER WAY

Downloading files this way is not the best idea especially for large files. PHP will require extra CPU / Memory to read and output file contents and when dealing with large files may reach time / memory limits.

A better way would be to use PHP to authenticate and grant access to a file, and actual file serving should be delegated to a web server using X-SENDFILE method (requires some web server configuration):

After configuring web server to handle X-SENDFILE, just replace readfile($filePath) with header('X-SENDFILE: ' . $filePath) and web server will take care of file serving, which will require less resources than using PHP readfile.

(For Nginx use X-Accel-Redirect header instead of X-SENDFILE)

Note: If you end up downloading empty files, it means you didn't configure your web server to handle X-SENDFILE header. Check the links above to see how to correctly configure your web server.

查看更多
不流泪的眼
3楼-- · 2018-12-31 07:04

.htaccess Solution

To brute force all CSV files on your server to download, add in your .htaccess file:

AddType application/octet-stream csv

PHP Solution

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=example.csv');
header('Pragma: no-cache');
readfile("/path/to/yourfile.csv");
查看更多
刘海飞了
4楼-- · 2018-12-31 07:07

Here is a more browser-safe solution:

    $fp = @fopen($yourfile, 'rb');

    if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
    header('Content-Type: "application/octet-stream"');
    header('Content-Disposition: attachment; filename="yourname.file"');
    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: ".filesize($yourfile));
}
else
{
    header('Content-Type: "application/octet-stream"');
    header('Content-Disposition: attachment; filename="yourname.file"');
    header("Content-Transfer-Encoding: binary");
    header('Expires: 0');
    header('Pragma: no-cache');
    header("Content-Length: ".filesize($yourfile));
}

fpassthru($fp);
fclose($fp);
查看更多
呛了眼睛熬了心
5楼-- · 2018-12-31 07:09

Nice clean solution:

<?php
    header('Content-Type: application/download');
    header('Content-Disposition: attachment; filename="example.csv"');
    header("Content-Length: " . filesize("example.csv"));

    $fp = fopen("example.csv", "r");
    fpassthru($fp);
    fclose($fp);
?>
查看更多
登录 后发表回答