【问题标题】:PHP script to download a file does work properly for .txt files but not image or video files用于下载文件的 PHP 脚本确实适用于 .txt 文件,但不适用于图像或视频文件
【发布时间】:2021-02-14 12:45:44
【问题描述】:

我在下载 php.ini 文件时遇到问题。我有一个文件夹,其中包含服务器根目录之外的文件(出于安全原因,但我认为这可能不是问题所在),我正在尝试使用下面的脚本下载文件,

其中$_POST['path']$filename(检查后)是我的文件夹的绝对路径,例如 /home/username/storage/filename.extension

我的服务器根路径是/home/username/www

当我尝试下载 .txt 文件时,似乎一切正常 - 我可以下载并打开它。

但是,当我下载图像或视频文件时,我计算机上的任何应用程序都无法打开该文件。 对于 .png 它表示我的文件不是 PNG 文件,对于 .jpg 它表示它不以 0x0a 0x0a 开头,等等。

每次我尝试下载某些东西时,我下载它的文件夹中文件的大小等于我下载的文件的大小.但是文件的格式/内容有问题。 我检查了我正在下载的目录中的文件,它们没有问题。问题仅在于下载的,因此由于某种原因我的脚本无法正确下载它们。

也许我的标题不正确?或者,文件大小可能存在问题(我的 txt 文件比图像小..,但即使是 300M 的视频也能在几秒钟内下载)? (但是,apache 错误日志中没有错误。)或者我做错了什么?

if(isset($_POST['path'])) {
  //Read the filename
  //+there are some checks on the path, to make sure user does not download a file which I dont want him to be able to download, but I dont think that is important, because the .txt file is downloaded normally
  $filename = $_POST['path'];

  //Check the file exists or not
  if(file_exists($filename)) {
      //Define header information
      header('Content-Description: File Transfer');
      header('Content-Type: application/octet-stream');
      header("Cache-Control: no-cache, must-revalidate");
      header("Expires: 0");
      header('Content-Disposition: attachment; filename="'.basename($filename).'"');
      header('Content-Length: ' . filesize($filename));
      header('Pragma: public');

      //Clear system output buffer
      flush();

      //Read the size of the file
      readfile($filename);
      //Terminate from the script
      die();
  }
  else{
      echo "File does not exist.";
  }
}
else
  echo "Filename is not defined."

【问题讨论】:

  • 上面的代码对我来说工作得很好。你是否检查了你尝试下载的文件的权限? www-data(或您的网络服务器运行的用户)应该具有文件的读取权限和目录的执行权限。
  • 是的,我检查了权限,但在我的情况下权限不是问题。如果文件夹的权限有问题,我可能无法下载文本文件;)。我也检查了每个下载文件的权限,但它们是文本文件的一些,所以它们没有问题。

标签: php file download http-headers file-handling


【解决方案1】:

似乎在readfile() 之前调用ob_clean() 方法很有帮助:),

更多信息,请参阅https://www.php.net/manual/en/function.ob-clean.php

这对我有用:

if(isset($_POST['path']))
{
//Read the filename
$filename = $_POST['path'];

//Check the file exists or not
if(file_exists($filename)) {


//Define header information
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Cache-Control: must-revalidate");
header('Content-Transfer-Encoding: binary');
header("Expires: 0");
header('Content-Disposition: attachment; filename="'.basename($filename).'"');
header('Content-Length: ' . filesize($filename));
header('Pragma: public');

ob_clean();    //<----- I had to add THIS LINE

//Clear system output buffer
flush();

//Read the size of the file
readfile($filename);
//Terminate from the script
die();
}
else{
echo "File does not exist.";
}
}
else
echo "Filename is not defined."

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-07
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    相关资源
    最近更新 更多