从MySQL中使用PHP提取BLOB图像数据

3

我在阅读关于将图像以二进制形式上传到数据库而非将它们放在服务器上的教程时,找到了以下方法:

PHP:

$image = chunk_split(base64_encode(file_get_contents($tmpfile)));
    mysql_query("INSERT INTO images (`img_location`, `caption`, `user`, `genre`, `when`) VALUES ('$image', '$caption', '$id', '$genre', '$when')");

我的问题是如何从数据库中获取数据,我已经阅读了几种方法来完成它,尝试了所有的方法,但无法弄清楚,我没有收到 MySQL 错误,以下是我尝试的方式:

$get_pics = mysql_query("SELECT * FROM images WHERE user='$id' ");
while($get_pics2 = mysql_fetch_array($get_pics))
{
$sixfour_enc = base64_decode($get_pics2['img_location']);

$new .= "<img src=\"".$sixfour_enc."\" >";
}

这个有点能用,但实际上它将原始二进制内容打印在IMG标签中。

我该如何将其编译为可读的图像?而且,在数据库中存储图像是不明智的吗?我应该像平常一样将它们存储在服务器上吗?

谢谢 -迈克

3个回答

6
如果您愿意,可以将图片存储在数据库中(不过仅将其存储为文件也没问题,选择适合自己的方式即可),但是请使用BLOB存储原始二进制数据(即不要使用base64编码)。获取file_get_contents的二进制数据后,可以直接在查询中嵌入它,只需先使用适当的转义函数(在您的情况下为mysql_real_escape_string)进行处理即可。
至于输出图像,您可以继续使用目前的方式,但必须以base64编码并使用data URI方案输出,例如:
echo '<img alt="embedded image" src="data:image/png;base64,' . chunk_split(base64_encode($get_pics2['img_location'])) . '">';

注意,嵌入式图像数据有一些优点和缺点。需要注意的一些重要缺点是base64编码的严重开销(比原始文件大约33%)和潜在的缓存问题。

这完全是有道理的,我在评估了性能损失后又返回到了旧的做事方式,但我只是随手一试,结果效果非常好!谢谢先生! - user1053263

2
如果您没有特殊原因需要将图像数据存储在数据库中,我强烈建议您按照正常方式处理。

这是因为,您的数据库引擎将承受显著的性能损失,因为您将获取和放置比必要更多的数据。

此外,在大多数情况下,MySQL表上的BLOB字段在大小方面明显大于其他表,并且性能较慢。

仅仅想象一下一旦您实施此操作对服务器的开销,我就感到害怕。 ;)

我认为这归结为可扩展性。一旦您的数据库填满,您的服务器就会变得不太响应,并最终成为一个真正的负担。您的下一个选择将是增加服务器RAM或修改代码以适应更大的负载。

以上是我的个人意见,希望对您有所帮助!

祝好运!


是的,我会按照常规方式来做。我曾尝试过一些新方法来测试它的工作原理,但后来意识到我的数据库会变得非常庞大。我在考虑是否采用这种方式更加安全和容易,但正如你所说,这很可能会对性能造成巨大影响。谢谢! - user1053263
1
没问题,我来帮忙! :) - jdalangin

0
其实,最好的方法是使用一个PHP脚本来输出带有正确头信息的图像二进制文件(比如getimage.php),然后用于生成HTML的脚本将会包含以下代码:
$get_pics = mysql_query("SELECT id FROM images WHERE user='$userid' ");
while($imglist = mysql_fetch_array($get_pics))
{
    $new .= '<img src="getimage.php?id='.$imglist['id'].'" title="'.$imglist['caption'].'" />';
}

所以HTML将会是这样的:
<img src="getimage.php?id=12345" title="the caption of" />

在表格images上,你必须有一个主键(为什么还没有?),比如说id

getimage.php”脚本将提取二进制并输出内容(假设字段img_location包含实际图像内容:

<?php
// this will output the RAW content of an image with proper headers
$id=(int)$_GET['id'];

$get_img = @mysql_fetch_assoc(@mysql_query("SELECT img_location FROM images WHERE id='$id' "));

$image = imagecreatefromstring(base64_decode($get_img['img_location']));
if ($image){
    //you may apply here any transformations on the $image resource
    header("Content-Type: image/jpeg"); //OR gif, png, whatever
    imagejpeg($image,null,75);          //OR imagegif, imagepng, whatever, see PHP doc.
    imagedestroy($image);               //dump the resource from memory
}
exit();
@mysql_close();
?>

这种方法将为您提供灵活性。 但是,您可能需要检查和清理变量,并选择另一种连接到MySQL的方法,如MYSQLi或PDO。 另一个好主意是使用准备语句来防止SQL注入。


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