php - MySQL 中存储的二进制数据被损坏

标签 php mysql sql pdo binary-data

我需要在 MySQL 数据库中存储 50 KiB - 500 KiB 二进制文件(实际上是 zlib 压缩文本文件)。假设有充分的理由这样做,而不是仅仅将它们写入文件系统,那么我遇到了数据库中数据损坏的问题。我用 PHP 和 Python 都把它拉出来了,都显示数据已损坏。

我曾尝试使用 PHP 模拟准备语句和非模拟准备语句来输入数据,以及简单地将数据放在查询中,就好像它是字符串一样。所有这些都导致数据损坏。

使用准备好的语句:

$options = array('PDO::ATTR_EMULATE_PREPARES' => FALSE);
$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2', $options);

$sql = 'INSERT INTO cache (body) VALUES (:body)';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':body', $body);

使用模拟的准备好的语句:

$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2');

$sql = 'INSERT INTO cache (body) VALUES (:body)';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':body', $body);

直接进入数据库:

$dsn = 'mysql:host=localhost;dbname=qb_cache;charset=utf8';
$pdo = new PDO($dsn, 'root', 'hunter2');

$sql = "INSERT INTO cache (body) VALUES ('{$body}')";
$stmt = $pdo->prepare($sql);

请注意,没有 PDO PDO::PARAM_* constant对于二进制数据!顺便说一句,我不认为我达到了 MySQL 字段的大小限制:

mysql> show variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.00 sec)

这是我尝试解码时得到的结果:

$ zlib-flate -uncompress < output_from_database
...snip...
74 ARP4s0B64R9P6oZOpe6262E}C k3A AFD001 Si IL4A57sflate: inflate: data: invalid block type


$ cat output_from_database | openssl zlib -d > decoded
140438369359520:error:29065064:lib(41):BIO_ZLIB_READ:zlib inflate error:c_zlib.c:570:zlib error:data error

使用Python从MySQL中提取数据,我看到该字段的大小是正确的,但我无法解压缩它::

>>> pprint(zlib.decompress(row[0]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -5 while decompressing data: incomplete or truncated stream

最佳答案

问题是列类型是blob,因为某种原因我认为blob是MySQL支持的最大数据类型。事实证明,当我实际查看并看到数据库中的大小为 65535 字节时,我明白数据正在被截断。 移至longblob解决了该问题。

对于下一个人:MySQL Data Type Storage Requirements .

关于php - MySQL 中存储的二进制数据被损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20181276/

相关文章:

php - 计算一个值出现的次数并将计数发送到另一列?

python - 如何在 Django ORM 查询中进行日期数学运算?

mysql - 如何在查询末尾添加一个额外的行,其值为 (previousRowColA + 1) 在 mysql 中?

php - 基于变量的表

php - 我应该在 MySQL 中使用 set-type 来获取用户的国家/地区信息吗?

MySQL 一对一关系

mysql - 使用 REF_CURSOR 转换 Oracle 存储过程并将全局变量打包到 Postgresql 或 MySQL

php - 将 select html5 变量放入 php 并在 mysql 查询中使用它作为限制?

php - 防止 PHP 中的跨站点脚本

sql - 如何截断为 MySQL 查询中的列返回的文本