Leer imagen desde un campo OLE Object de Access con PHP

Parece una tarea sencilla. Es tan fácil como hacer un query y tomar el dato, pero las cosas siempre se complican cuando se trabaja con formatos cerrados.

La pruebas que he realizado han sido con un archivo Access 2007 con una tabla y un campo del tipo “OLE Object”. Luego agregamos una imagen de prueba de la siguiente manera:

Click en Insert Object

Seleccionamos un archivo y hacemos click en Ok

Con esto ya tenemos nuestra BD access lista para ser consultada.

Ahora, para conectarnos a la  BD Access con PHP usamos AdoDb usand DSN-less de la siguiente manera:

require ‘adodb.inc.php’;

$db =&ADONewConnection(“access”);

$path = ‘/tmp/mydb.mdb’;

$dsn=”Driver={Microsoft Access Driver {*.mdb}};Dbq=$path”;

$db->connect($dsn);

if ($db)  {

$sql = “SELECT image from table”;

$result = $db->Execute($sql);

while (!$rs->EOF) {

$image_data = $rs->fields[0];

}

}

El valor de $image_data contiene el OLE Package que a su vez contiene la imagen agregada, pero el problema aquí es de leer este formato OLE package. Buscando en google encontré algunas  fuentes que dicen poder hacerlo, pero usando aspx, aunque no lo he probado, pues no quiero comprar una licencia de Visual Studio de $800, al parecer hay que buscar dentro del OLE Package unos bytes que definen un archivo de imagen en este caso buscaría los siguientes strings dependiendo el formato del archivo…

const string BITMAP_ID_BLOCK = “BM”;
const string JPG_ID_BLOCK = “u00FFu00D8u00FF”;
const string PNG_ID_BLOCK = “u0089PNGrnu001an”;

const string GIF_ID_BLOCK = “GIF8”;
const string TIFF_ID_BLOCK = “II*u0000”;

Pero para leer este stream según esta fuente hay que convertir esta data en utf7 y luego buscar el id de JPG. Como todo esto parece raro lo que hice fue ver el código hex de algunos archivos jpeg usando un programa llamado ghex  (sudo apt-get install ghex). Al abrir diferentes imágenes veremos que se repite estos famosos bytes FFD8FFE0

Ahora que tenemos la “llave” solamente tenemos que convertir $image_data a hex usando la función pack y luego hacer lo inverso con unpack:

$result     = unpack(‘H*’,$image_data);

$image_to_hex = $result[1];

$jpg_id = ‘ffd8ffe0’;

$pos = strrpos($image_to_hex, $jpg_id);

if ($pos === false) {

echo ‘No es posible generar archivo’;}

else {

$image_to_hex = substr($image_to_hex, $pos,strlen($image_to_hex));

header(‘Content-Type: image/jpeg’);

echo $result_image = (pack(‘H*’,$image_to_hex));

}

Podemos guardar el resultado de $result_image en un archivo usando file_put_contents y eso es todo!

 

Comments

Saved my life!!!!

Was having the same issue with MS Word files stored in an MSSQL’s image field. Was driving nuts until I found in the internet that it wasn’t openning because of the OLE header. Then I found your page and saw how to strip the damn header.

Thank you!!!

No se por que puse el comentario en inglés :s Supongo que ya es tarde y hace mucho que estoy luchando contra M$! 🙂

Gracias de nuevo 😛