【问题标题】:Uploading images to MySQL (blob) with PHP使用 PHP 将图像上传到 MySQL (blob)
【发布时间】:2020-10-10 13:49:56
【问题描述】:

出于安全原因,我决定将用户个人资料图片上传到数据库,而不仅仅是一个文件夹并上传图片地址,这将是一个好主意。

我以前从未在后端处理过文件上传问题,但从各种来源了解了这一点,我相信我做的一切都是正确的。但是没有上传有用的二进制数据。

在 php.ini 中

file_uploads=开启

在前端

<form enctype="multipart/form-data" method="post" autocomplete="on" action="upload/">       
    <p>
        <input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg" required />
        <label for="avatar">*Profile photo</label>

    </p>

    <p class="submitter two-thirds columns">
        <input type="submit" value="Apply" />
    </p>
     
</form>

在后台

if(isset($_SESSION['id']))
    $UserID = $_SESSION['id'];
else exit(1);

if (!empty($_FILES['avatar'])){
    $photo = fopen($_FILES['avatar']["tmp_name"], 'rb');
    $photo_mime = $_FILES['avatar']["type"]; 
}
else exit(1);

$values_data = array(
    $UserID,
    $photo,
    $photo_mime,
);


$sql = "INSERT INTO `user`
    (
        UserID,
        photo,
        photo_mime
    )
    VALUES
    (
        :UserID,
        :photo,
        :photo_mime
    )
    ON DUPLICATE KEY UPDATE
        photo = :photo,
        photo_mime = :photo_mime
    ";

$sth = $dbh->prepare($sql);


$sth->bindValue(':UserID', $values_data[0]);
$sth->bindValue(':photo', $values_data[1]);
$sth->bindValue(':photo_mime', $values_data[2]);
$sth->execute();

并且数据库确实获得了一些信息

但是,这些图像二进制文件都是 1KB。看看他们里面有这样的数据

资源 ID #13

所以二进制文件会被弄乱或丢弃在某个地方......但是在哪里?

【问题讨论】:

  • 出于好奇,将图像存储在数据库中解决了哪些安全问题?
  • @MagnusEriksson 我的第一个选择是带有图像地址的公共文件夹。即使我停止此文件夹可导航或可索引,也可以通过操作 URL 轻松浏览用户照片,除非我的所有图像名称都有大量随机字符......而且我不确定这有多安全将是 tbh
  • 您可以将图像保留在文档根目录之外,并拥有一个充当代理的 PHP 文件:image.php?name=foo.jpg,并让image.php 文件从图像文件夹读取并输出图像数据。然后您还可以在输出图像之前添加检查以查看用户是否已登录。它将就像您的数据库解决方案一样,但不需要将 files 存储在数据库中,而不是存储在 file 系统(它们所属的位置)中。..
  • @MagnusEriksson 哦,好吧。 file_get_contents 看起来更有希望。 var_dump 为此输出大量明显随机的 unicode,因此看起来是正确的。上传到数据库失败,但很快就会检查
  • 如果下面的答案有帮助,请告诉我。如果是,请随时接受它,让其他用户知道它已解决。

标签: php mysql image pdo blob


【解决方案1】:

fopen() 不返回文件的内容。它返回一个文件指针资源,然后您可以将其传递给fread() 之类的东西以获取内容。

类似:

$handler = fopen($_FILES['avatar']["tmp_name"], 'r');
$file = fread($handler, filesize($_FILES['avatar']["tmp_name"]));
fclose($handler);

更简单的方法是使用file_get_contents()

$file = file_get_contents($_FILES['avatar']["tmp_name"]);

它将在一行中为您提供内容。

【讨论】:

  • 这解决了眼前的问题。我相信与数据库的连接需要太长时间(Mysql Server has gone away 错误)所以我认为我会实施你的“在文档根目录下”的建议
  • 只是为了 100% 清楚:它不是文档根目录的“下方”(可以解释为下方/内部),它应该是文档根目录的“外部”(如上方/旁边) (以防止客户直接访问)。但是,是的,这可能是一个更好的选择。
  • 我认为鉴于上下文很明显我们不是在谈论 www/public_html/img 类型的路径
  • 100% 清晰总是好的。有时您可能会认为某些事情是显而易见的,而其他人则不会:-) 这也是为了向任何未来的访问者澄清它。我已经学会了尽可能少的假设。
猜你喜欢
  • 2016-05-26
  • 1970-01-01
  • 2013-11-25
  • 2021-11-05
  • 2017-08-16
  • 2018-08-26
  • 2015-05-25
  • 2017-01-06
  • 2011-11-01
相关资源
最近更新 更多