首页 > 解决方案 > PHP readfile() 下载原始文件的精确副本

问题描述

标题可能令人困惑,但我会在这里尝试解释。

我有一个文件样本。该文件是一个简单的 .xml 文件,但具有 .ciff 扩展名和特定编码(使用的编码是 UCS2-LE BOM)。

TEST001.ciff 中的内容是:

<?xml version="1.0" encoding="UTF-16"?>

就这样。

现在我正在尝试从浏览器下载此文件(不显示内容,但实际上将其下载到下载文件夹中),这是我目前在 download.php 文件中使用的代码:

<?php
require_once('../../../private/initialize.php');
require_login();

// Redirect if the logged in user is not with admin level
if($session->level == 'user') {
    redirect_to(url_for('/index.php'));
}

include(SHARED_PATH . '/staff_header.php');

if (!empty(h($_GET['filename']))) {

    // We have filename request, lets try download it
    if (file_exists('Files/' . h($_GET['filename']))) { 

        // We have the file on the server so we can download it
        header("Pragma: public");
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.basename('Files/' . h($_GET['filename'])).'"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Content-Length: ' . filesize('Files/' . h($_GET['filename'])));
        readfile('Files/' . h($_GET['filename']));
        exit;

    } else {
        // The file was not found on the server
        $session->message('The requested file was not found on the server.', false);
        redirect_to(url_for('staff/ciff/index.php'));
    }
} else {
    // The file request was invalid
    $session->message('Invalid file request.', false);
    redirect_to(url_for('staff/ciff/index.php'));
}

include(SHARED_PATH . '/staff_footer.php'); 
?>

到目前为止一切顺利,当我单击下载超链接时,文件 TEST001.ciff 被下载到我的下载文件夹中,但是当我打开下载的文件时,我可以看到以下内容:

<!doctype html>

<html lang="en">
<head>
<title>NESI Ticketing - Admin Area</title>
<meta charset="utf-8">
<link rel="stylesheet" media="all" href="/nesiticket/public/stylesheets/staff.css" />
</head>

<body>
<header>
  <h1>NESI Ticketing User Area</h1>
</header>

<navigation>
  <ul>
            <li>Hello,  FirstName LastName</li><br />
    <li><a href="/nesiticket/public/index.php">Home Page</a></li>
    <span>&nbsp;</span>
    <li><a href="/nesiticket/public/staff/index.php">Main Menu</a></li>
    <span>&nbsp;</span>
    <li><a href="/nesiticket/public/staff/logout.php">Logout</a></li>
          </ul>
</navigation>

ÿþ< ? x m l   v e r s i o n = " 1 . 0 "   e n c o d i n g = " U T F - 1 6 " ? > 

上面代码底部的部分在 Notepad++ 中看起来像这样 在此处输入图像描述

我可以下载原始文件的精确副本吗?我的代码哪里出错了?

标签: php

解决方案


问题肯定是包含包含 HTML 的 PHP 文件。如果 PHP 解析器遇到<?php ?>标签之外的任何其他内容,它将作为字符串回显给任何接受它的客户端(您的浏览器,作为文件)。

如果这种包含发生在您的实际下载逻辑周围,例如在您的情况下使用 staff_header.php,它包含在实际文件内容之前在您的输出中看到的 HTML,那么您当然会得到一个包含 HTML 和文件内容,甚至可能是错误的编码。

可能的解决方案各不相同,并且由于您已经在使用包含文件等的低级别 PHP,如果您在包含您的 Staff_header.php 之前移动下载逻辑可能就足够了。

当下载代码退出时,如果您的下载发生,标头将永远不会包含在内,但请注意,通常情况下,像这样混淆逻辑是相当不干净的。

我建议保持这种逻辑的分离和更高的顺序管理,即使它只是另一个包含 if 子句的 PHP 文件,它决定是否应该执行下载或 HTML 逻辑。


推荐阅读