我在MS ACCESS数据库中将图像作为BLOB。到目前为止,我已经使用它们与PHP的odbc access,它工作正常。这是简化程序:
code:
<?php
ini_set("odbc.defaultlrl", "5M");
$dbName = $_SERVER["DOCUMENT_ROOT"]."\\..\db\\teknofo.mdb";
$con = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=".$dbName,'','') or die('Ups');
ob_clean();
header('Content-Type: image/*');
$sql = "SELECT photo FROM Medlemmer WHERE Id=17";
$rd = odbc_exec($con, $sql);
if (odbc_fetch_row($rd)) { echo odbc_result($rd,"photo"); }
odbc_close($con);
ob_end_flush();
?>
我正在转换为MySql但是必须使用MS Access来获得一些时间: 因此我使用PDO制作新代码,但我无法正确读取数据。
这是新的
<?php
$dbName = $_SERVER["DOCUMENT_ROOT"]."\\..\db\\teknofo.mdb";
$con = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=$dbName; Uid=; Pwd=;");
$sql = "SELECT photo FROM Medlemmer WHERE id=?";
$st = $con->prepare($sql);
$st->execute(array(17));
$st->bindColumn('photo', $photo, PDO::PARAM_LOB);
$st->fetch(PDO::FETCH_BOUND);
odbc_longreadlen($st, 131072);
odbc_binmode($st,ODBC_BINMODE_CONVERT);
ob_clean();
header('Content-Type: image/*');
if ($rd = $st->fetch(PDO::FETCH_BOUND)) {
echo $rd['photo'];
ob_end_flush();
$con = null;
?>
最后一段代码使用MySql工作(更改了连接字符串),但没有使用MS Access。
我已经在网上搜了很长时间但是找不到解决办法。
有人可以帮忙吗?
我可以使用第一个代码,但我也需要能够处理BLOB用于其他目的。
答案 0 :(得分:4)
PHP和Access ODBC驱动程序从来都不是最好的朋友,显然PDO_ODBC和Access ODBC驱动程序仍然如此。这里的两个皱纹是
BLOB以ASCII字符串形式返回,表示图像数据的十六进制值(例如,'424D7AC000 ...'),
该字符串每255个字符包含一个虚假的NULL字符。
我设法工作的代码是:
<?php
$dbName = $_SERVER["DOCUMENT_ROOT"]."\\test.mdb";
$con = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=$dbName; Uid=; Pwd=;");
$sql = "SELECT Photo FROM Clients WHERE id=?";
$st = $con->prepare($sql);
$st->execute(array(1));
$st->bindColumn(1, $photoChars, PDO::PARAM_LOB);
$st->fetch(PDO::FETCH_BOUND);
// $photoChars is a long string of hex, e.g., '424D7A...'
// PDO+Access_ODBC apparently injects a NULL every 255 characters,
// so remove them first
$photoChars = str_replace("\0", "", $photoChars);
// create array of character pairs (e.g.: '42', '4D', '7A', ...)
$photoArray = str_split($photoChars, 2);
// convert to numeric values
for ($i = 0; $i < sizeof($photoArray); $i++) {
$photoArray[$i] = hexdec($photoArray[$i]);
}
// pack into binary string
// ref: http://stackoverflow.com/a/5473057/2144390
$photoData = call_user_func_array("pack", array_merge(array("C*"), $photoArray));
header('Content-Type: ' . image_type_to_mime_type(IMAGETYPE_PNG));
header('Content-Disposition: attachment; filename="untitled.bmp"');
echo $photoData;
答案 1 :(得分:1)
我知道这是一个旧线程,但我偶然发现同样的问题,@ gord-thompson的回答帮助了我。但我意识到有一种更简单,更快捷的方法。
您需要做的只是删除\0
- 字节,然后直接调用pack
:
// PDO+Access_ODBC apparently injects a NULL every 255 characters,
// so remove them first
$photoChars = str_replace("\0", "", $photoChars);
//Pack the HEX-String into a binary string and encode it with base64
base64_encode(pack("H*", $photoChars));
因此不再需要str_split
,hexdec
。您所要做的就是将pack
来自PDO + Access的HEX数据转换为二进制格式。
答案 2 :(得分:0)
使用Gord Thompson的解决方案我遇到了一个错误。我不知道为什么结尾对某些二进制文件搞砸了,但这就是我修复它的方法。
一种修补未知腐败来源的黑客攻击// create array of character pairs (e.g.: '42', '4D', '7A', ...)
$photoArray = str_split($photoChars, 2);
// at this point some jpegs were ending in 'ff', '0D', '09'
// they should end in 'ff', 'D9'
$photo_end = sizeof($photoArray)-1;
if($photoArray[$photo_end] === '9'){
$photoArray[$photo_end - 1] = 'D9'; // fix the previous element to be end of image
unset($photoArray[$photo_end]); // remove the last element
}
// pack into binary string
// ref: http://stackoverflow.com/a/5473057/2144390
$photoData = call_user_func_array("pack", array_merge(array("C*"), $photoArray));