PHP强制下载和刷新解决方案无效

use*_*680 5 javascript php session refresh download

最终目标:单击第1页上的链接,最后下载文件并刷新页面1.使用PHP提供不在公共HTML中的下载.

做法:

第1页. 链接传输到第2页,获取我正在使用的文件的get变量引用.

第2页. 使用在刷新页面1之前需要更新的信息更新相关的SQL数据库.设置"firstpass"会话变量.从get变量设置会话变量"getvariablereference".重定向到第1页.

第1页. 如果首先传递会话变量集.设置第二次传递会话变量.取消设置第一个传递变量.刷新页面.在重新加载时,页面将使用更新的SQL数据库信息进行重建(在第2页上更改).

刷新页面1. 如果第二次传递会话变量设置.运行下载服务标头序列.

这是第1页.我没有显示第1页中具有初始链接的部分.既然没关系.

// REFERSH IF FIRSTPASS IS LIVE
if ($_SESSION["PASS1"] == "YES"){
    $_SESSION["PASS1"] = "no";
    $_SESSION["PASS2"] = "YES";
    echo "<script>document.location.reload();</script>";
    }
if ($_SESSION["PASS2"] == "YES"){
    // Grab reference data from session:
        $id = $_SESSION['passreference'];
                // Serve the file download
                        //First find the file location
                        $query = "SELECT * from rightplace
                              WHERE id = '$id'";
                        $result = mysql_query($query);
                        $row = mysql_fetch_array($result);
                        $filename = $row['file'];
                        $uploader = $row['uploader'];   
                            // Setting up download variables
                                $string1 = "/home/domain/aboveroot/";
                                $string2 = $uploader;
                                $string3 = '/';
                                $string4 = $filename;
                                $file= $string1.$string2.$string3.$string4;
                                $ext = strtolower (end(explode('.', $filename)));
                                //Finding MIME type
                                    if($ext == "pdf" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/pdf');
                                        readfile($file);
                                        }                                   
                                    if($ext == "doc" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/msword');
                                        readfile($file);
                                        }                   
                                    if($ext == "txt" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: text/plain');
                                        readfile($file);
                                        }                   
                                    if($ext == "rtf" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/rtf');
                                        readfile($file);
                                        }
                                    if($ext == "docx" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
                                        readfile($file);
                                        }
                                    if($ext == "pptx" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/vnd.openxmlformats-officedocument.presentationml.presentation');
                                        readfile($file);
                                        }
                                    if($ext == "ppt" && file_exists($file)) {
                                        header("Content-disposition: attachment; filename= '$filename'");
                                        header('Content-type: application/vnd.ms-powerpoint');
                                        readfile($file);
                                        }
                                        }
Run Code Online (Sandbox Code Playgroud)

第2页上的脚本工作正常.它更新了sql数据库并正确地重定向到主页面.我还检查过它设置了"$ _SESSION ['passreference'];" 正确,第1页上的任何内容都不会取消它.

所以,这就是对情况的全面解释.我很难过.会发生什么,正如我所说,第2页工作正常.然后它踢到第1页,刷新,然后不推送任何下载.我知道下载脚本可以工作,并且文件可以下载(在没有整个刷新序列的情况下进行检查).

我基本上有两个问题:

  1. 谁能发现什么出错?

  2. 任何人都可以概念化更好的方法吗?

Joh*_*n C 6

即使给出代码,很难远程调试这样的东西,你发布的片段就像​​你说的那样工作.你检查过错误日志了吗?最可能的罪魁祸首是header()在完成其他输出后发送问题.

在处理文件下载时,我认为在新的页面/窗口上启动下载的任何地方都更容易,因此不存在破坏标题的风险.也许是使用第三页启动实际下载的略微改变的序列:

  1. 第1页链接到第二页做魔术,重定向回到第1页
  2. 然后,第1页在新窗口中生成第3页,启动下载.

这个答案中有一个很好的示例代码,用于加载下载的新窗口.


SDw*_*rfs 0

我刚刚稍微修改了你的 PHP 代码。特别是,您将获得有关问题所在的更多信息。如果您收到新的错误消息之一,只需尝试此代码并阅读以下注释,其中解释了发生的情况。另请阅读下面的“注释”部分,它解释了为什么您可能无法从 PHP 访问文件,即使该文件已存在且位于正确的目录中。

  1. 使用 window.location.reload(); 而不是文档.位置...
  2. 我添加了一个 error() 函数。您可以向其中添加更多 HTML,以便它以您想要的布局生成页面。您也可以将错误记录到本地文件中。有一个私有信息参数,用于将敏感信息作为数据库错误(可以包含 SQL)传递给函数。为了高效使用,您不应将其显示给用户。相反,您可以将其记录到文件中或仅为特权用户(例如管理员)显示它。
  3. 检查天气 $id 是否设置。如果没有,则返回 error() 消息;如果会话未正确更新,则可能会发生这种情况。
  4. 我添加了“$id=addslashes($id);” 出于安全原因。例如,如果您的 id 可以设置为 $id = "' OR 1"(SQL 注入)等值,您可能会遇到麻烦。如果您确定不会发生这种情况,则可以将其删除。
  5. 它在数据库查询后检查 $result 变量。例如,如果您的数据库连接未建立或脚本无法连接,这将产生一个 error() 输出来通知您。如果 SQL 语法有错误,例如表名错误,也会发生同样的情况。
  6. 它还检查是否从数据库中获取了有效的 $row。如果没有返回行,您的 $id 可能是错误的(您的数据库中没有这样的条目)。
  7. 我将您的字符串操作重写为 $filepath = $rootpath 。“/”。$上传者。“/”。$文件名;其中 $rootpath 是之前设置的,末尾没有“/”;这更容易阅读...
  8. 扩展和 MIME 类型现在放入数组中,而不是使用大量“if-then”块,这样更易​​于维护。而且该块内的代码是相似的......所以我们只需要编写一次。
  9. 如果文件扩展名未知,则发送默认 MIME 类型(内容类型:“application/octet-stream”)。
  10. 我们检查 file_exists() 并输出一条错误消息,并给出 $filename 以允许检查路径是否正确......

所以这是源代码:

<?php 

function error($message, $info = "") {
  echo "ERROR: $message<br>";
  echo "PRIVATE-INFO: $info"; // probably you only want to log that into a file?
  exit;
}

// REFERSH IF FIRSTPASS IS LIVE
if ($_SESSION["PASS1"] == "YES") {
  $_SESSION["PASS1"] = "no";
  $_SESSION["PASS2"] = "YES";
  echo "<script>window.location.reload();</script>";
  exit;
}


if ($_SESSION["PASS2"] == "YES") {
  // Grab reference data from session:
  $id = $_SESSION['passreference'];

  if (!$id) error("Internal Error ('id' not set)");

  // Select file location from DB
  $id = addslashes($id);
  $query = "SELECT * from rightplace WHERE id = '$id'";
  $result = mysql_query($query);

  if (!$result) error("DB-query execution error", mysql_error());

  $row = mysql_fetch_array($result);
  mysql_free_result($result);

  if (!$row) error("File with ID '$id' was not found in DB.");

  $filename = $row['file'];
  $uploader = $row['uploader'];

  // Setting up download variables
  $rootpath = "/home/domain/aboveroot";
  $filepath = $rootpath . "/" . $uploader . "/" . $filename;
  $ext = strtolower(end(explode('.', $filename)));

  // Serve the file download

  // List of known extensions and their MIME-types...
  $typelist = array(
      "pdf"  => "application/pdf",
      "doc"  => "application/msword",
      "txt"  => "text/plain",
      "rtf"  => "application/rtf",
      "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
      "ppt"  => "application/vnd.ms-powerpoint"
  );

  // set default content-type
  $type = "application/octet-stream";

  // for known extensions, assign specific content-type
  if (!isset($typelist[$ext])) $type = $typelist[$ext];

  if (file_exists($filepath)) {
    header("Content-disposition: attachment; filename= '$filename'");
    header("Content-type: $type");
    readfile($filepath);
  } else {
    error("Error: File '$filepath' was not found!", $filepath);
  }
}

?>
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 即使文件存在,也可能会发生文件未找到错误。如果发生这种情况,这很可能是一种安全机制,阻止 PHP 脚本访问 HTML 根目录之外的文件。例如,php 脚本可以在“chrooted”环境中执行,其中根目录“/”被映射到“/home/username/”。因此,如果您想访问“/home/username/dir/file”,您需要在 PHP 脚本中写入“/dir/file”。如果你的 root 设置为“/home/username/html”,情况可能会更糟;那么您将无法访问“html”目录下的目录。要解决这个问题,您可以在 HTML 根目录中创建一个目录,并在其中放置一个名为“.htaccess”的文件。在其中写入“DENY FROM ALL”,这将阻止浏览器请求访问该目录(只有脚本可以访问它)。这仅适用于 apache 服务器。但是其他服务器软件也有类似的解决方案...更多信息可以在以下位置找到:http ://www.php.net/manual/en/ini.core.php#ini.open-basedir

  2. 另一种可能性是您的文件访问权限(对于上传的文件)没有以允许您的脚本访问它们的方式设置。启用某些安全设置(在 Linux 服务器上)后,您的 PHP 脚本只能访问与为脚本文件设置的“所有者”相同的用户所拥有的文件。通过“ftp”上传后,这很可能是 ftp 用户的用户名。如果在 shell 上进行编辑,这将是当前用户的用户名。=> 但是:上传的文件有时会分配给运行网络服务器的用户(例如“www-data”、“www-run”或“apache”)。因此,找出它是什么并将您的脚本分配给该所有者。

  3. 对于文件上传,您应该使用 move_uploaded_file(...) ,解释如下:www.php.net/manual/en/function.move-uploaded-file.php ;如果不这样做,文件访问权限可能错误,或者您可能无法访问该文件。