【问题标题】:Force directly linked file to download强制直接链接文件下载
【发布时间】:2023-03-15 00:29:01
【问题描述】:

有没有办法提供一个文件的直接链接并强制浏览器使用 PHP 下载它?

例如http://www.website.com/directory/file.jpg

我们在这里处理的是巨大的文件,特别是 Chrome 似乎在渲染图像时遇到了问题,因此用户在直接访问文件时看到的只是一个空白屏幕。即使他们仍然可以在空白屏幕中右键单击并下载文件,但还是很混乱。

我们曾经从 PHP 输出文件,但遇到内存问题,因此改用提供直接链接。这些文件高达约 5GB,它们并非全是图像。我们有 zip、PDF、PSD 等。

目前,该文件是通过一个 PHP 脚本请求的,该脚本接受文件的 ID 并获取其 URL。然后 PHP 脚本将用户重定向到文件的完整 URL。

我们如何确保强制下载并且我们不会遇到较大文件的内存问题?

谢谢

【问题讨论】:

  • 也许this answer 会帮助你。
  • 这似乎是一个网络服务器配置问题;只需将Content-Type: application/octet-stream 添加到特定目录中的所有文件即可。

标签: php download


【解决方案1】:

你需要设置headers强制下载

        $file = 'upload_directory_path/'.$image_name;

        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            ob_clean();
            flush();
            readfile($file);
            exit;
        }

【讨论】:

    【解决方案2】:
    <?php 
    //file path
    $file = 'monkey.gif';
    
    if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
    

    【讨论】:

    • 这类似于我们最初的做法。问题是当有人试图下载一个 5GB 的文件时,它会吃掉内存。这应该适用于那些大文件吗?
    • 是的,如果您的服务器具有正确的配置,它会起作用。但是 5 GB 下载只需压缩文件并调用简单的 URL
    【解决方案3】:

    只需使用X-Sendfile,但您需要先配置它...使用XSendFilePath

    if (file_exists($file)) {
        header("X-Sendfile: $file");
        header("Content-Type: application/octet-stream");
        header(sprintf("Content-Disposition: attachment; filename=\"%s\"", basename($file)));
        exit();
    }
    

    注意*在验证和提供文件之前,请确保 $file 已正确转义

    XSendFilePath 仅适用于其他服务器的 Apache,请参阅:Caching HTTP responses when they are dynamically created by PHP

    【讨论】:

      猜你喜欢
      • 2018-03-14
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 2018-06-26
      • 2011-09-07
      相关资源
      最近更新 更多