PHP PDO MS Access如何读取blob图像?

时间:2014-03-11 12:34:05

标签: php mysql ms-access pdo blob

我在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用于其他目的。

3 个答案:

答案 0 :(得分:4)

PHP和Access ODBC驱动程序从来都不是最好的朋友,显然PDO_ODBC和Access ODBC驱动程序仍然如此。这里的两个皱纹是

  1. BLOB以ASCII字符串形式返回,表示图像数据的十六进制值(例如,'424D7AC000 ...'),

  2. 该字符串每255个字符包含一个虚假的NULL字符。

  3. 我设法工作的代码是:

    <?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_splithexdec。您所要做的就是将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));