所以我以前有这个问题,但这是PHP版本的问题。事实并非如此。
从不更改代码,它工作正常。仅更改了主机,但我不认为应该有问题。
我唯一得到的就是垃圾代码。
下载链接如下:https://example.com/forum/download.php?file=TEST.zip
<?php
$file = 'TEST.zip';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
while (ob_get_level()) {
ob_end_clean();
}
readfile($file);
exit;
}
?>
答案 0 :(得分:0)
在代码有限的情况下,我能想到的最好的办法是删除此内容?>
,我讨厌此标签,我从不亲自使用它。
如果在PHP之类的HTML之后没有任何内容,则不需要它,并且实际上可以破坏文件下载
?>
//empty line here
由于PHP的工作方式,它将TAG之外的任何内容作为内容输出,因此取决于调用发生的位置,它们之前或之后的任何内容都可以显示在文件中。
我想exit
可以解决这个问题,但是我不喜欢该标签。因为如果您在应用程序中包含一堆PHP文件,则只需使用一个文件,这些文件的标签外应有空格以弄乱事情,并祝您好运。
此位
while (ob_get_level()) {
ob_end_clean();
}
清除输出缓冲区(如果已设置),如果这是文件的全部内容,则可能未设置。我个人会这样:
<?php
//start output buffering
ob_start();
//be careful with casing
// - Windows is case insensitive
// - Linux is case sensitive
//for example if the file is named text.zip
//it will work on Windows, but be mission on Linux
$file = 'TEST.zip';
//without the file no download can happen
// -- so kill it before header are sent
// -- that way if file is missing we can easily debug it.
if (file_exists($file)) die("Missing required file {$file}");
header('Content-Description: File Transfer');
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
$debug = '';
while (ob_get_level()) {
//end all output buffering before file download
//save this stuff, there could be useful debug information in here.
$debug .= ob_get_clean();
}
if(!empty($debug)){
//put "stuff" in a file
// -- FILE_APPEND = append to end of log
// -- lock writing on the file for this opperation
// --- its possible 2 clients could download the same time.
file_put_contents(__DIR__.'/download_error.txt', $debug, FILE_APPEND|FILE_EX);
}
//finally output the file
readfile($file);
//this is good
exit;
这样,您可以记录输出而不会弄乱下载。基本上,您会将这些东西扔掉,这可能是有用的信息。
除此之外,其他一切看起来都还不错,我的意思是并没有太多可能出错的地方。如果我知道garbage code.
是什么,也许我可以提供更多帮助。也许原始文件不好,谁知道...
我不能肯定地说这能解决您的问题,我所说的大部分只是我个人对日志记录和执行顺序的偏爱。但这可能无法解决。
安全性
最后,我要提一提,您应该非常小心地使用此?file=TEST.zip
,恶意用户可以这样做。
?file=../../../../etc/passwd //which is a bad example (unless PHP is admin)
基本上,他们可以使用您的输入来横向目录结构。更好的方法是像这样
$file = false;
switch($_GET['file']){
case 'TEST.zip': //you can even use a hash
$file = 'TEST.zip';
break;
//you can even use a hash instead of the name
//this prevents errors caused by things like quotes in the filename.
//something as simple as switch(md5($_GET['file'])), is finr
case 'uiOzAWe8aser':
//then the user has no access to your filesystem
$file = 'TEST.zip';
break;
default: die('File not found '.$_GET['file'];
}
当然,在许多情况下这可能不切实际,但是您可以在数据库等中进行验证。