miércoles, 27 de mayo de 2015

Imágenes en BaseDatos y Xojo

Cuando se intenta obtener imágenes en bases de datos como PostgreSQL, MySQL o MSSQL desde Xojo tenemos problemas, y es que no funciona la propiedad PictureValue debido a que son bases de datos diseñadas (generalmente) para acceder sobre red, es decir, los datos se tiene que "codificar" (encode) a texto y después enviarlo a la base de datos; por el contrario una base de datos como SQLite los datos son binarios.

Si ud. almacena las imágenes desde xojo, el siguiente código funciona en PostgreSQL, MySQL, MSSQL y ODBC:

Para almacenar:

  ' Image.png, db, la tabla tbl_images y el registro con id=1 deben existir.
  ' el campo image debe ser tipo bytea (postgres) o text

  Dim p As Picture= SpecialFolder.Desktop.Child("image.png")
  Dim mb As MemoryBlock= p.GetData(Picture.FormatPNG)
  Dim s As String= EncodeBase64(mb.StringValue(0, mb.Size))

  Dim sql As String= "UPDATE tbl_images SET image= '"+ s+ "' WHERE id=1"
  db.SQLExecute(sql)

  If db.Error Then
    System.Log(System.LogLevelError, "PostgreSQL(DB:"+ db.DatabaseName+ _
    ",U:"+ db.UserName+ "):"+ EndOfLine+ EndOfLine+ sql)
    Return
  End If

Para obtener:

  Dim rs As RecordSet= db.SQLSelect("SELECT * FROM tbl_images WHERE id=1")

  mb= DecodeBase64(DecodeHex(rs.Field("image").StringValue))
  p= Picture.FromData(mb)

  'Canvas1 debe existir
  If p<> Nil Then Canvas1.Backdrop= p


Si ud NO almacena las imágenes desde xojo, bueno, las cosas son un poco más difícil, para obtener imágenes desde bases de datos se tiene que hacer las operaciones inversas de las que cuales fueron almacenadas, por ejemplo en PosrgreSQL para almacenar imágenes en campos bytea puede usarse:

En PHP usando escape_byea:

<?php
  // Connectar a la base de datos
  $dbconn = pg_connect('dbname=foo');

  // Leer en un fichero binario
  $data = file_get_contents('image1.jpg');

  // Escapar el dato binario
  $escaped = pg_escape_bytea($data);

  // Insertarlo en la base de datos
  pg_query("INSERT INTO gallery (name, data) VALUES ('Pine trees', '{$escaped}')");?>
En PHP usando bin2hex:

<?php
  // Connect to the database
  $dbconn = pg_connect( 'dbname=foo' );
  
  // Read in a binary file
  $data = file_get_contents( 'image1.jpg' );
  
  // Escape the binary data
  $escaped = bin2hex( $data );
  
  // Insert it into the database
  pg_query( "INSERT INTO gallery (name, data) VALUES ('Pine trees', decode('{$escaped}' , 'hex'))" );

  // Get the bytea data
  $res = pg_query("SELECT encode(data, 'base64') AS data FROM gallery WHERE name='Pine trees'");  
  $raw = pg_fetch_result($res, 'data');
  
  // Convert to binary and send to the browser
  header('Content-type: image/jpeg');
  echo base64_decode($raw);
?>
En PHP usando lo_import:
<?php
 $uploaddir = '/home/postgres/';
 $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
 $name = $_POST['name'];

 if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
 {   // echo "File is valid, and was successfully uploaded.\n";
 }
 else   {   echo "File size greater than 300kb!\n\n";   }

 echo "'$name'\n";

 $conn = pg_pconnect("dbname=test user=postgres password=postgres");
 $query = "insert into image values ('$name', lo_import('$uploadfile'), 'now')";
 $result = pg_query($query);

 if($result)
 {
     echo "File is valid, and was successfully uploaded.\n";
     unlink($uploadfile);
 }
 else
 {
     echo "Filename already exists. Use another filename. Enter all the values.";
     unlink($uploadfile);
 }
 pg_close($conn);
 ?>

Y en otras bases de datos sucede algo similar, no hay un estandar.Para obtener se debe utilizar DecodeBase64 o DecodeHex (o los dos) para llevar el valor del campo a una variable MemoryBlock y utilizar Picture.FromData para convertirlo en imagen.

No hay comentarios:

Publicar un comentario