PHP 强制下载会导致文件损坏问题

3

首先...我知道这个问题在这个网站上已经被讨论了很多次,我已经读了过去几个小时的评论和解决方案,但是没有什么帮助。

我在PHP中创建了一个小脚本来强制下载。这只是我正在尝试在我的网站上使用的代码的一部分,因为我不想用太多无关的代码来垃圾邮件你,但它仍然包括错误的输出。

这段代码中的所有内容都是使用10.6KB的.PNG文件进行测试的。

注意:原始问题已经被删除,因为它已经得到了解决。然而,当我将我的代码片段实现到我的网站中时,我遇到了另一个问题。

我创建了一个下载文件的函数:

<?php
function download_file($file) 
{
    $known_mime_types=array(
        "htm" => "text/html",
        "exe" => "application/octet-stream",
        "zip" => "application/zip",
        "doc" => "application/msword",
        "jpg" => "image/jpg",
        "php" => "text/plain",
        "xls" => "application/vnd.ms-excel",
        "ppt" => "application/vnd.ms-powerpoint",
        "gif" => "image/gif",
        "pdf" => "application/pdf",
        "txt" => "text/plain",
        "html"=> "text/html",
        "png" => "image/png",
        "jpeg"=> "image/jpg"
    );  
    if(!is_readable($file)) die('<p class="error">File not found or inaccessible!</p>');

    $file_extension = strtolower(substr(strrchr($file,"."),1));
    if(array_key_exists($file_extension, $known_mime_types)){
        $mime_type=$known_mime_types[$file_extension];
    } else {
        $mime_type="application/force-download";
    };

    $fsize = filesize($file);

    header('Content-Type: ' .$mime_type);
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: '.$fsize);
    header('Accept-Ranges: bytes');
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Pragma: public');
    header('Cache-Control:');
    readfile($file);
    exit();
}
?>

我调用函数的download.php文件:

<!DOCTYPE html>
<?php
require_once 'connect.inc.php';
require_once 'core.inc.php';
require_once 'download_file.php';
?>
<html>
<head>
    <title>x3d Download</title>
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/styles.css" type="text/css"/>  
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
<?php
if (loggedin())
{
    include_once 'navbar_loggedin.php';
}
else 
{
    include_once 'navbar_loggedout.php';
}
?>
<div class="container" width="900px">
    <h2>Downloads</h2>
<?php
    $sql = "SELECT * FROM `files`";
    $result = mysql_query($sql);
    if (!$result)
    {
        echo '<p>No downloads available.</p>';
    }
    else 
    {
        echo '<table class="table table-hover"><tr>';
        echo '<tr><th>Filename</th>';
        echo '<th>Filetype</th>';
        echo '<th></th>';
        if (loggedin())
        {
            if (getuserlevel($_SESSION['user_id']) == 'Administrator')
            {
                echo '<th></th>';
            }
        }
        while($row = mysql_fetch_assoc($result)) 
        {
            echo '<tr><td><p>'.$row['file_name'].'</p></td>';
            echo '<td><p>'.$row['file_type'].'</p></td>';
            echo '<td><a href="download.php?download='.$row['file_id'].'"><span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span></a></td>';
            if (loggedin())
            {
                if (getuserlevel($_SESSION['user_id']) == 'Administrator')
                {
                    echo '<td><a class="red" href="download.php?delete='.$row['file_id'].'"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a></td>';
                }
            }
        } 
        echo '</tr></table>';
    }
?>
<?php
if (isset($_GET['download'])) 
{
    $sql = "SELECT `file_name` FROM `files` WHERE `file_id`='".$_GET['download']."'";
    if ($result = mysql_query($sql)) 
    {
        $row = mysql_fetch_assoc($result);
        $file = "uploads/" . $row['file_name'];
        download_file($file);
    }
}

if (isset($_GET['delete'])) 
{
    $sql = "SELECT `file_name` FROM `files` WHERE `file_id`='".$_GET['delete']."'";
    if ($result = mysql_query($sql)) 
    {
        $row = mysql_fetch_assoc($result);
    }

    if ($row['file_name'] == "")
    {
        echo '<p class="error">File does not exist.</p>';
    }
    else
    {
    $filepath = "uploads/".$row['file_name'];
    $sql = "DELETE FROM `files` WHERE `file_id`='".$_GET['delete']."'";
    if (file_exists($filepath)) 
    {
        try
        {
            if (unlink($filepath))
            {
                if ($result = mysql_query($sql))
                {
                    header('Location: download.php');
                }
            }
        }
        catch (Exception $e)
        {
            echo '<p class="error">Could not delete file.</p>';
        }
    }
    }
}
?>
</div>
</body>
</html>

已测试调用函数的代码,并且我的 SQL 查询确实返回了正确的值。

该图像包含我 HTML 源代码的一部分和原始图像...

有人可以帮我吗?


“失败的下载会话”是什么?浏览器可能输出了哪些特定错误信息?例如“由于X原因下载失败”。 - al'ein
@Alan Machado,浏览器错误有两种形式,具体取决于我使用的文件扩展名。 1)无法保存C:\ Users \ XX \ AppData \ Local \ Temp \ XX.png.part,因为无法读取源文件。 2)没有给出此错误,但Firefox只是说下载失败。 - Pieter Moens
@andrewsi 我用Notepad++打开它,里面包含了一张原始图片和我的HTML源代码。 - Pieter Moens
你能试试 $file = __DIR__."/uploads/" . $row['file_name']; 吗? - Federkun
@Federico 也许你也想亲自看看问题?我已经将我的网站上传到一个免费的网络主机上。 http://x3dnet.herobo.com/download.php - Pieter Moens
显示剩余6条评论
1个回答

4

你的代码很好。但是你下载的不是图片,而是致命错误:

<br />
<b>Fatal error</b>:  Call to undefined function fileread() in <b>/var/www/html/test.php</b> on line <b>18</b><br />

fileread($file);修改为readfile($file);,然后它就能正常工作了。

下次遇到“140字节的损坏文件”,试着以文本文件的方式打开它。


好的,我错过了它是“反转”的 :) - al'ein
这真是一个巨大的脸掌 >.< 非常感谢!它确实解决了我的代码问题,现在我将尝试在我的其余代码中实现它,但我有信心它会起作用。 - Pieter Moens
当我尝试使用函数调用这段代码片段时,仍然会出现损坏的文件。 - Pieter Moens
@Frederico 各种类型的文件,但我目前仍在使用图像进行测试。我已经用Notepad++打开了损坏的文件,它包含我的HTML源代码和图像。(我应该更新这个问题并发布我的新代码吗?) - Pieter Moens
@Federico,问题已更新,希望你能帮我解决。 - Pieter Moens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接