强制使用 PHP 下载文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1465573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:43:13  来源:igfitidea点击:

Forcing to download a file using PHP

phphttpdownload

提问by Elitmiar

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.

我的服务器上有一个 CSV 文件。如果用户点击一个链接,它应该下载,但它会在我的浏览器窗口中打开。

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.phpfile:

现在我的csv.php文件的内容:

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.

现在我的问题是它正在下载,但不是我的 CSV 文件。它会创建一个新文件。

回答by robjmills

.htaccess Solution

.htaccess 解决方案

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

要强制下载服务器上的所有 CSV 文件,请添加 .htaccess 文件:

AddType application/octet-stream csv

PHP Solution

PHP解决方案

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

回答by AtanuCSE

Or you can do this using HTML5. Simply with

或者您可以使用 HTML5 执行此操作。简单地与

<a href="example.csv" download>download not open it</a>

回答by Michael Borgwardt

This cannot be done reliably, since it's up to the browser to decide what to do with an URL it's been asked to retrieve.

这不能可靠地完成,因为由浏览器决定如何处理被要求检索的 URL。

You can suggestto the browser that it should offer to "save to disk" right away by sending a Content-disposition header:

您可以通过发送 Content-disposition 标头向浏览器建议它应该立即提供“保存到磁盘”:

header("Content-disposition: attachment");

I'm not sure how well this is supported by various browsers. The alternative is to send a Content-type of application/octet-stream, but that is a hack (you're basically telling the browser "I'm not telling you what kind of file this is" and depending on the fact that most browsers will then offer a download dialog) and allegedly causes problems with Internet Explorer.

我不确定各种浏览器对此的支持程度。另一种方法是发送一个内容类型的应用程序/八位字节流,但这是一个黑客(你基本上是在告诉浏览器“我不会告诉你这是什么类型的文件”,并且取决于大多数浏览器将提供一个下载对话框)并据称会导致 Internet Explorer 出现问题。

Read more about this in the Web Authoring FAQ.

Web 创作常见问题解答中阅读更多相关信息

EditYou've already switched to a PHP file to deliver the data - which is necessary to set the Content-disposition header (unless there are some arcane Apache settings that can also do this). Now all that's left to do is for that PHP file to read the contents of the CSV file and print them - the filename=example.csvin the header only suggests to the client browser what name to use for the file, it does not actually fetch the data from the file on the server.

编辑您已经切换到一个 PHP 文件来传递数据——这是设置 Content-disposition 标头所必需的(除非有一些神秘的 Apache 设置也可以做到这一点)。现在剩下要做的就是让该 PHP 文件读取 CSV 文件的内容并打印它们 -filename=example.csv标题中的仅向客户端浏览器建议用于文件的名称,它实际上并不从服务器上的文件。

回答by Franz

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);

回答by Gumbo

Configure your server to send the file with the media type application/octet-stream.

配置您的服务器以发送媒体类型的文件application/octet-stream

回答by StampedeXV

This means that your browser can handle this file type.

这意味着您的浏览器可以处理这种文件类型。

If you don't like it, the easiest method would be offering ZIP files. Everyone can handle ZIP files, and they are downloadable by default.

如果您不喜欢它,最简单的方法是提供 ZIP 文件。每个人都可以处理 ZIP 文件,默认情况下它们是可下载的。

回答by vdbuilder

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);
?>

回答by Chris Harrison

A previous answer on this page describes how to use .htaccess to force all files of a certain type to download. However, the solution does not work with all file types across all browsers. This is a more reliable way:

此页面上的先前答案描述了如何使用 .htaccess 强制下载某种类型的所有文件。但是,该解决方案不适用于所有浏览器中的所有文件类型。这是一种更可靠的方法:

<FilesMatch "\.(?i:csv)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

You might need to flush your browser cache to see this working correctly.

您可能需要刷新浏览器缓存才能看到它正常工作。

回答by hussain

If you are doing it with your application itself... I hope this code helps.

如果你用你的应用程序本身来做...我希望这段代码有帮助。

HTML

HTML

In href -- you have to add download_file.php along with your URL:

在 href - 您必须添加 download_file.php 以及您的 URL:

<a class="download" href="'/download_file.php?fileSource='+http://www.google.com/logo_small.png" target="_blank" title="YourTitle">

PHP

PHP

/* Here is the Download.php file to force download stuff */

<?php
    $fullPath = $_GET['fileSource'];
    if($fullPath) {
        $fsize = filesize($fullPath);
        $path_parts = pathinfo($fullPath);
        $ext = strtolower($path_parts["extension"]);

        switch ($ext) {
            case "pdf":
                header("Content-Disposition: attachment; filename=\"" . $path_parts["basename"]."\""); // Use 'attachment' to force a download
                header("Content-type: application/pdf"); // Add here more headers for diff. extensions
                break;

            default;
                header("Content-type: application/octet-stream");
                header("Content-Disposition: filename=\"" . $path_parts["basename"]."\"");
        }

        if($fsize) { // Checking if file size exist
            header("Content-length: $fsize");
        }
        readfile($fullPath);
        exit;
    }
?>

回答by Dima L.

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

要强制下载,您可以使用Content-Type: application/force-download大多数浏览器支持的标头:

function downloadFile($filePath)
{
    header("Content-type: application/octet-stream");
    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.

以这种方式下载文件并不是最好的主意,尤其是对于大文件。PHP 将需要额外的 CPU/内存来读取和输出文件内容,并且在处理大文件时可能会达到时间/内存限制。

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):

更好的方法是使用 PHP 来验证和授予对文件的访问权限,实际的文件服务应该使用 X-SENDFILE 方法委托给 Web 服务器(需要一些 Web 服务器配置):

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.

配置web服务器来处理后X-SENDFILE,只需替换readfile($filePath)header('X-SENDFILE: ' . $filePath),web服务器就会负责文件服务,这比使用PHP需要更少的资源readfile

(For Nginx use X-Accel-Redirectheader instead of X-SENDFILE)

(对于 Nginx,使用X-Accel-Redirectheader 而不是X-SENDFILE

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

注意:如果您最终下载了空文件,则意味着您没有配置您的网络服务器来处理X-SENDFILE标头。检查上面的链接以了解如何正确配置您的 Web 服务器。