【问题标题】:PHP PDO MS Access how to read blob images?PHP PDO MS Access如何读取blob图像?
【发布时间】:2014-04-15 01:48:38
【问题描述】:

我在 MS ACCESS 数据库中有图像作为 BLOB。到目前为止,我已经将它们与 PHP 的 odbc 访问一起使用,并且工作正常。下面是简化程序:

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

【问题讨论】:

    标签: php mysql ms-access pdo blob


    【解决方案1】:

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

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

    2. 该字符串每 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;
    

    【讨论】:

    • 谢谢戈德 - 这真的有效 - 但我们不得不做这样的事情真是太遗憾了。但我担心当我尝试更新 blob 数据时会出现什么问题?????
    • @ErikP 很久以前我得出的结论是,从 PHP 使用 Access 数据库时(到目前为止)最好的方法是使用 COM 和 ADODB.Connection。老实说,我不记得我是否能够使用 PDO_ODBC 和 Access ODBC 驱动程序获得 BLOB 更新。
    • 感谢您的提示。我将研究 COM,看看我是否可以将它用于 Access 和 MySql;
    【解决方案2】:

    我知道这是一个旧线程,但我偶然发现了同样的问题,@gord-thompson 的回答帮助了我。但我意识到有一种更简单、更快捷的方法。

    您需要做的就是去掉\0-Bytes,然后直接调用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-Data转成二进制即可。

    【讨论】:

      【解决方案3】:

      使用 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));
      

      【讨论】:

        猜你喜欢
        • 2012-02-13
        • 1970-01-01
        • 1970-01-01
        • 2013-09-27
        • 2022-01-23
        • 1970-01-01
        • 2012-05-29
        • 1970-01-01
        相关资源
        最近更新 更多