PHP readfile()下载原始文件的精确副本

问题描述 投票:2回答:2

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

我有一个文件样本。此文件是一个简单的.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 ++ enter image description here中看起来像这样

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

php
2个回答
3
投票

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

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

可能的解决方案各不相同,因为您已经在处理包含文件等的低级别PHP,如果您在包含staff_header.php之前移动了下载逻辑,则可能就足够了。

当下载代码退出时,如果您的下载发生,则不会包含标题,但请注意,通常情况下,混合这样的逻辑是相当不洁净的。

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


0
投票

这将读取文件并将其作为下载发送到浏览器。

这里的PHP代码。

$filename = 'Files/' . h($_GET['filename'];

if(file_exists($filename)){

    //Get file type and set it as Content Type
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    header('Content-Type: ' . finfo_file($finfo, $filename));
    finfo_close($finfo);

    //Use Content-Disposition: attachment to specify the filename
    header('Content-Disposition: attachment; filename='.basename($filename));

    //No cache
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');

    //Define file size
    header('Content-Length: ' . filesize($filename));

    ob_clean();
    flush();
    readfile($filename);
    exit;
}

© www.soinside.com 2019 - 2024. All rights reserved.