【问题标题】:Downloading files stored in MySQL using PHP使用 PHP 下载存储在 MySQL 中的文件
【发布时间】:2015-04-07 04:47:52
【问题描述】:

我无法让我成功上传的文件位于我的 MySQL 数据库中名为 appFiles 的表中的 blob 字段中,以便返回并显示。我已经阅读了很多演示,大多数都相似,但没有一个能解决我的问题。我很久以前做过一次,但是那个旧项目的代码是使用 mysqli 完成的,我想成为 100% 基于 PDO。这是我处理文件的代码部分:

} else if($ctoken === $utoken) {
    // Our tokens match, proceed with the view

    $stmt = $conn->prepare("SELECT fileMime, fileSize, fileName, file FROM $database.appFiles WHERE fileID = :fileid");
    $stmt->bindParam(':fileid', $_GET['fid'], PDO::PARAM_INT, 11);
    $stmt->execute();
    $fRes = $stmt->fetchAll();

    header('Content-Disposition: attachment; filename="' . $fRes[0][fileName] . '"');
    ob_clean();
    flush();
    echo $fRes[0][file];
    exit;
}

现在我知道数据已成功从数据库中选择出来。我可以通过执行 var_dump($fRes) 轻松检查这一点。它似乎都在那里,当然,其中大部分是二进制混乱,并且似乎在许多其他在屏幕上毫无意义的混乱中作为问号出现。

当我在 PDF 文档上测试它时,它只是在屏幕上吐出二进制文件。当我使用 DOC/DOCX 文件对其进行测试时,它至少会尝试在 MS Word 中打开它,但随后告诉我文件转换中断并显示一个空文档(显示 docx 时)或显示一个不正确的长文档和 gobblygook 混乱数百页(尝试显示 doc 文件时)。

我已经尝试了一系列不同的标题选项,大多数结果不同,没有一个符合预期。那么如何让它以可理解的格式成功吐出文件呢?

编辑感谢 Darren 在下面提供的链接,我现在将其用作查看存储在数据库中的文件的代码:

try {
    $stmt = $conn->prepare("SELECT * FROM $database.users WHERE uID = :uid");
    $stmt->bindParam(':uid', $uID, PDO::PARAM_INT, 11);
    $stmt->execute();
    $uRes = $stmt->fetchAll();
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); }

$ctoken = $_COOKIE['cookieToken'];
$utoken = $uRes[0]['sessionToken'];

if($ctoken !== $utoken) {
    // Our tokens don't match, kill the session
    header("Location: ./logOut.php");
    exit;
} else if($ctoken === $utoken) {
    // Our tokens match, proceed with the view

    $stmt = $conn->prepare("SELECT fileMime, fileSize, fileName, file FROM $database.appFiles WHERE fileID = :fileid");
    $stmt->bindParam(':fileid', $_GET['fid'], PDO::PARAM_INT, 11);
    $stmt->execute();
    $fRes = $stmt->fetchAll();

    header("Content-Type: application/octet-stream");
    header("Content-Transfer-Encoding: Binary");
    header("Content-disposition: attachment; filename=\"".$fRes[0][fileName]."\"");
    echo readfile($fRes[0][file]);

    exit;
}

它们现在至少似乎提示我下载并保存它们,或者使用正确的查看器打开它们。这很好。但是,由于每次文件仅以 0 字节的形式到达时,仍然有一些问题......最后,有人知道如何解决这个问题并让它正常工作吗?

第二次编辑我已经对这种情况进行了大量测试,发现从数据库中检索文件实际上根本没有问题。我的上传系统似乎有问题,并且文件在那里受到了某种创伤。如果我通过使用 phpmyadmin 将已上传的文件(名称、类型、大小等都正确导入)替换为原始文件,将其“重新加载”到数据库中,则下载界面会根据需要对其进行完美处理。这里要学习的一课 - 不要仅仅因为文件的所有属性(如大小、mime、名称等)看起来都正确,就认为它是正确上传的!现在来了解我的上传文件为何/在哪里弄乱了文件……如果您知道发生这种情况的位置或原因,请visit here

【问题讨论】:

  • 您可能需要阅读this,其中概述了如何强制下载。
  • file 列包含什么?如果是文件内容,那么您只需回显它。如果它是文件的路径,那么您只需调用readfile(不带回显)。
  • 你好海纳。文件本身作为介质 blob 存储在 MySQL 数据库中,并且不存储在目录中的任何位置。所以它是从 MySQL PDO 请求中提取的数据的一部分,而 $fRes[0][file] 是(应该是)文件本身。
  • 我把最后一行从 - echo readfile($fRes[0][file]); - 成为 - echo $fRes[0][file];但结果是一样的。它的大小为 1 个字节,比以前多 1 个字节,但肯定无法使用,而且比它应该的要少得多......!

标签: php mysql pdo


【解决方案1】:

只需替换

echo readfile($fRes[0][file]); 

echo $fRes[0][file]; 

根据您的代码,file 字段包含文件内容。因此,您只需 echo 即可。

【讨论】:

  • 嗨 Lorenz,请查看我上面最近的评论 - 我已经完成了你指定的操作,但它不起作用。
  • 那么告诉我:数据库中的文件内容在哪里?
  • 文件内容存储在一个单独的表中,专门用于文件收集和处理,在一个设置为 medum blob 的字段中(文件大小限制为最大 5Mb)。该字段具有 BINARY 属性。没有设置其他特殊属性。
  • Lorenzo 的回答被接受,因为它是正确的,只是回答了我并不真正需要的问题,因为发现实际问题在于上传过程,而不是提取/下载过程。
猜你喜欢
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 2011-12-28
  • 2021-01-31
相关资源
最近更新 更多