使用PHP将Blobs插入到MySql数据库中

18

我正在尝试将一张图片存储到数据库中,但出现了问题。这是我的表结构:

mysql> describe ImageStore;
+---------+----------+------+-----+---------+-------+
| Field   | Type     | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| ImageId | int(11)  | NO   | PRI | NULL    |       |
| Image   | longblob | NO   |     | NULL    |       |
+---------+----------+------+-----+---------+-------+
2 rows in set (0.01 sec)

这是我的查询,它应该插入图片,或者至少我希望如此:

//Store the binary image into the database
                $tmp_img = $this->image['tmp_name'];
                $sql = "INSERT INTO ImageStore(ImageId,Image)               
                VALUES('$this->image_id','file_get_contents($tmp_image)')";
                mysql_query($sql); 

如果我打印 file_get_contents($tmp_image) 的值,那么屏幕上会显示大量数据。但是这个值没有被存储在数据库中,这就是我面临的问题。

4个回答

46

问题

$sql = "INSERT INTO ImageStore(ImageId,Image)
        VALUES('$this->image_id','file_get_contents($tmp_image)')";

这在PHP中创建一个名为$sql的字符串。暂时忘记MySQL,因为你还没有执行任何查询。你只是在构建字符串。

PHP的魔力意味着您可以在双引号内写入变量名——比如$this->image_id——并且变量仍然会被自动扩展。

这个功能称为“变量插值”,不适用于函数调用。所以,你这里所做的只是将字符串"file_get_contents($tmp_image)"写入数据库。


解决方案(1)

因此,要连接调用file_get_contents($tmp_image)的结果,您必须跳出字符串并显式地执行操作:

$sql = "INSERT INTO ImageStore(ImageId,Image)
        VALUES('$this->image_id','" . file_get_contents($tmp_image) . "')";

(即使仅从语法高亮中,您也可以看到它是如何工作的。)


解决方案(2)

现在您面临的问题是,如果二进制数据包含任何',则查询无效。因此,您应该通过mysql_escape_string对其进行清理,以便进行查询操作:

$sql = "INSERT INTO ImageStore(ImageId,Image)
        VALUES('$this->image_id','" . mysql_escape_string(file_get_contents($tmp_image)) . "')";

解决方案(三)

现在你有一个非常大的字符串,你的数据库也变得臃肿。

尽可能避免将图片存储在数据库中,除非必要。


@LightnessRacesinOrbit。关于“不喜欢在数据库中存储大文件”...这取决于哪个数据库。 - Pacerier

4
继续解释Tomalak的评论,你不能在引号内运行函数。
尝试:
$sql = "INSERT INTO ImageStore(ImageId,Image)               
        VALUES('{$this->image_id}','".file_get_contents($tmp_image)."')";

3

试试这个:

$tmp_img = $this->image['tmp_name'];
$sql = "INSERT INTO ImageStore(ImageId,Image)               
  VALUES('$this->image_id','" . addslashes(file_get_contents($tmp_image)) . "')";
mysql_query($sql);

4
请注意,在大多数数据库中使用 addslashes() 进行参数转义可能会导致安全问题。 - PHP 手册 - Tamás Bolvári
PDO::使用prepare(),但它也应该像addslashes()一样使用某些东西,因此我们应该更喜欢PHP本地解决方案,即addslashes()。它完美地工作。 - jacouh

2

如上所述,您只是将字符串"file_get_contents($tmp_image)"保存到数据库中,但您需要运行函数file_get_contents
在将其保存到数据库之前,请使用哈希算法(例如base64_encode)对图像进行哈希处理。


图像可能包含一些非法字符(例如--,",'等),这可能会在执行查询时导致问题。 - Shahrokhian
没有哈希或任何其他检查,这可能会导致 SQL 注入攻击。 - Shahrokhian
2
你根本不需要哈希。只需转义单引号和反斜杠以防止字符串模式中断即可。 - Lightness Races in Orbit
你说得没错,但还有另一种选择,我们可以像字符串一样发送和接收图像到浏览器,大多数浏览器可以将base64字符串转换为图像,但对于SQL注入和自定义错误,我更信任你的解决方案。 - Shahrokhian

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