PHP:提供文件下载而不提供直接链接

PHP:提供文件下载而不提供直接链接

我想提供发票供下载。目前我使用的是简单的编号方案(invoice-01.pdf、invoice-02.pdf 等)。我知道我可以使用哈希来隐藏数据。

是否也可以使用 PHP 并通过不让用户直接指向发票来提供发票?

答案1

甚至还有这样的例子php.net

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?> 

或者稍微扩展一下

<?php
if ( can_this_file_be_downloaded() ) {
  header('Content-type: application/pdf');
  header('Content-Disposition: attachment; filename="invoice.pdf"');
  readfile("{$_GET['filename']}.pdf");
} else {
  die("None shall pass");
}
?>

答案2

Sam 有答案。同样将它们放在带有 .htaccess 的目录中:

Authname Private
AuthType basic
require user noadmittance

如果他们知道 URL,这将阻止直接访问。您仍然可以使用 readfile() 从 PHP 脚本中读取它。

答案3

我找到了这本出色的指南:如何通过 PHP 提供大文件服务

lighttpd 技巧特别有用 - 如果您的 PHP 恰好在 lighttpd 下运行,则脚本只需要设置“X-Sendfile”标头,lighttpd 就会为您读取并发送文件(并且它知道如何发送文件)。

更新:

Lighttpd 具有此功能,并且 Apache2 有一个 mod_xsendfile。

(引自NginX 文档

答案4

一般来说,您应该在流式传输文件之前清理输出缓冲区,否则可能无法打开。如果您正在下载 EXE,代码签名证书可能已损坏。对于未进行代码签名的 EXE,这可能无关紧要,但这是确保代码签名仍然完好无损的最干净的方法,只需提供文件而不提供“额外”的标头/输出。

这与另一个答案很接近,但ob_clean();已插入到标题之前。

function serve_file($filepath, $new_filename = null) {
    $filename = basename($filepath);
    if (!$new_filename) {
        $new_filename = $filename;
    }
    $mime_type = mime_content_type($filepath);
    ob_clean();
    header('Content-type: ' . $mime_type);
    header('Content-Disposition: attachment; filename="' . $new_filename . '"');
    readfile($filepath);
}

用法:

serve_file($url, $filename);

例子:

$url = "example.exe";
$filename = "Example123.exe";
serve_file($url, $filename);

相关内容