In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.

Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.

Cargar Imagen en SQLite y luego mostrarla

Foro público de Xailer en español
Responder
Claudio C
Mensajes: 60
Registrado: Dom Sep 20, 2015 8:13 pm
Ubicación: Buenos Aires

Cargar Imagen en SQLite y luego mostrarla

Mensaje por Claudio C »

Estimados
Lucho hace varios dias ( y pierdo ) tratando de hacer una rutina que lea una imagen del disco y la cargue en una tabla sqlite.
La idea seria luego leer la imagen de la tabla y mostrarla en el background de pantalla.

Si me dan una pista/ejemplo lo agradezco.
Claudio
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5706
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por jfgimenez »

Claudio,

Para guardar la imagen:

Código: Seleccionar todo

cImagen := Memoread( "imagen.jpg" )
::oDatabase:Execute( "INSERT INTO Imagenes(Id,Imagen) VALUES( 1, x'" + StringToHex( cImagen ) + "' )" )
Para ponerla de fondo en el formulario:

Código: Seleccionar todo

::oBkgnd := TPicture():LoadFromStream( ::oDatabase:QueryValue( "SELECT Imagen FROM Imagenes WHERE Id=1" ) )
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
XeviCOMAS
Mensajes: 582
Registrado: Sab Mar 12, 2011 8:16 pm

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por XeviCOMAS »

y... ¿se puede "guardar" un archivo cualquiera??? Pdf, Jpg, Doc, Xls

El campo para "salvar" el archivo en una SQLite o MariaDb ¿de que tipo tiene que ser???
Un Saludo,
Xevi.
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5706
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por jfgimenez »

Xevi,

sí, se puede guardar lo que quieras. En SQLite el campo tiene que ser BLOB, y en MariaDB será MediumBlob o LargeBlob dependiendo de lo que quieras guardar.

Y para guardar binarios en MariaDB, también funciona el código anterior, pero tiene un límite en el tamaño de la sentencia. Lo mejor es usar directamente un dataset y asignar el valor al campo correspondiente. Xailer internamente graba los blobs en "chunks", y evita el problema del tamaño del buffer de comunicación.
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
XeviCOMAS
Mensajes: 582
Registrado: Sab Mar 12, 2011 8:16 pm

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por XeviCOMAS »

Gracias por responder.

Me está funcionando correctemente, y ya guardo ficheros Jpg, Txt, ini, Pdf... en campos "LONGBLOB" en MariaDB

Ahora una inquietud... ¿és "seguro" guardarlo de esta manera??? lo digo por no "cargar" demasiado una tabla MariaDB o por si puede crear problemas de corrupción de datos, lentitud al cargar/leer la tabla...
No se, vosotros que más entendeis, cómo lo veis???

Yo hasta ahora, al trabajar en DBFs, guardava imágenes PDFs i demás archivos en el mismo disco, guardando en la base de datos el "link" donde se alojaba ese/esos archivos. Pero el tema con SQL cambia, y si accedo remotamente a los datos en el servidor, debo de guardar esas imágenes, ficheros en el servidor, por lo que veo interesante poder guardarlos en la misma tabla.

Este es el código que utilizo, por si a alguien le puede servir.

Código: Seleccionar todo

FUNCTION xOpenFileMDB( nAssent, aFitxers, n )
   Local cFile := GetTempDirectory() + aFitxers[n,1]

   HB_MemoWrit( cFile, AppData:oDScompta:QueryValue( "SELECT contentfile FROM fitxers WHERE assent = " + AllTrim(Str(nAssent)) + " AND namefile='" + StrSQL(aFitxers[n,1]) + "'" ) )

RETURN {|| ShellExecute( 0, "open", cFile, 0, 0, SW_SHOWNORMAL ) }
*
*
PROCEDURE xGuardaFitxerMDB( self, nAssent, cCarpeta )
   Local aIdioma := { { "Sobreescriure el fitxer?", "¿Sobreescribir el archivo?" },;
                      { "El fitxer ja existeix", "El fichero ya existe" } }

   WITH OBJECT TFileOpenDlg():Create()
   If :Run()
      If Len( AppData:oDScompta:QueryArray( "SELECT namefile FROM fitxers WHERE assent = " + AllTrim(Str(nAssent)) + " AND namefile='" + StrSQL(:cFileNameOnly) + "'" ) ) = 0
         AppData:oDScompta:Execute( "INSERT INTO fitxers(assent,namefile,contentfile) VALUES( " + AllTrim(Str(nAssent)) + ", '" + StrSQL(:cFileNameOnly) + "', x'" + StringToHex( Memoread( :cFullFileName ) ) + "' )" )
      Else
         If xMsgDlg( aIdioma[1,AppData:nIdioma], aIdioma[2,AppData:nIdioma], mbRETRYCANCEL, mbDEFBUTTON2, IDI_QUESTION, { "&Si", "&No" } ) = mrCANCEL
            RETURN
         EndIf
         AppData:oDScompta:Execute( "UPDATE fitxers SET contentfile = " + "x'" + StringToHex( Memoread( :cFullFileName ) ) + "' WHERE assent = " + AllTrim(Str(nAssent)) + " AND namefile='" + StrSQL(:cFileNameOnly) + "'" )
      EndIf

      TRY //OR/Albarans
      If( !::lLblFitxersBlink, ::lLblFitxersBlink := .T., )
      ::oTimerBlink:lEnabled := ::lLblFitxersBlink .or. ::lLblNotesBlink .or. ::lLblObserBlink .or. ::lLblNotaClientBlink
      CATCH
      END
   EndIf
   :Destroy()
   END

RETURN
*
*
PROCEDURE xBorraCarpetaMDB( self, nAssent )
   Local aIdioma := { { "Està Segur que vol Eliminar la Carpeta i TOT el seu Contingut?", "¿Está Seguro de Eliminar la Carpeta y TODO su Contenido?" },;
                      { "CONFIRMAR ELIMINAR", "CONFIRMAR ELIMININAR" } }

   If xMsgDlg( aIdioma[1,AppData:nIdioma], aIdioma[2,AppData:nIdioma], mbRETRYCANCEL, mbDEFBUTTON2, IDI_QUESTION, { "&Si", "&No" } ) = mrRETRY
      Application:lBusy := .T.

      AppData:oDScompta:Execute( "DELETE FROM fitxers WHERE assent = " + AllTrim(Str(nAssent)) )
      ::lLblFitxersBlink := .F.
      ::oTimerBlink:lEnabled := .F.

      TRY
      ::Browse1Change()
      END

      Application:lBusy := .F.
   EndIf
RETURN
Un Saludo,
Xevi.
Avatar de Usuario
ignacio
Site Admin
Mensajes: 9246
Registrado: Lun Abr 06, 2015 8:00 pm
Ubicación: Madrid, Spain
Contactar:

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por ignacio »

Buenas,

A mi personalmente no me gusta hacer crecer las bases de datos con ese tipo de archivos. Además, si tienes que 'compartir' algún documento con terceros (clientes, proveedores, ...) es un engorro tener que mandarle el documento completo por correo electrónico. Obliga a descargarlo en tu máquina. añadirlo a un correo y enviarlo. Es mucho más sencillo mandar una URL.

Mi recomendación, sube los archivos a la nube por FTP o equivalente (Nuestra clase TWebDataSource lo incorpora) y simplemente guarda la URL en la base de datos. Utiliza miniaturas de imágenes para la base de datos.

Saludos
Ignacio Ortiz de Zúñiga
[Equipo de Xailer / Xailer team]
https://www.xailer.com
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5706
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por jfgimenez »

Xevi,

yo lo hago de la siguiente forma:

- En MariaDB, utilizo una BD distinta para la gestión documental, y la tabla que contiene los documentos es de tipo MyISAM, no InnoDB. MyISAM no es ACID, y no me hace falta para esto, pero es más rápida y consume menos recursos. Si utilizas una tabla InnoDB verás que llegará un momento en que se vuelva lenta y pesada, aunque no te darás cuenta hasta que ocupe varios GB

- Cuando son imágenes, guardo también una miniatura, que es lo que el usuario ve en un carrusel de fotos. Sólo recupero la imagen completa si el usuario la abre. Esto ahorra mucho tráfico de red y carga del servidor. En el resto de documentos muestro su icono, y lo obtengo directamente del sistema

- También utilizo un sistema de "caché", que consiste en una BD SQLite local (la guardo en el directorio temp del puesto), debidamente cifrada para evitar problemas de protección de datos. Esto me permite no tener que acceder a las imágenes del servidor salvo que se hayan modificado o añadido nuevas

Este sistema lo llevo usando varios años y hasta ahora no he tenido problemas. Tengo un cliente cuya BD de documentos ocupa ya más de 10GB
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
XeviCOMAS
Mensajes: 582
Registrado: Sab Mar 12, 2011 8:16 pm

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por XeviCOMAS »

Ignacio, Jose,
Gracias por responder.

Tomo buena nota de que me comentan.

Ignacio, para servidor local y con las tan queridas DBFs, hasta hoy estoy utilizando la carpeta en el Servidor, y llamando/accediendo a cada documento a través de un link para acceder a él.
Para tener que montar un FTP a cada cliente que vaya a utilizar mi aplicación, no me saldria a cuenta al tratarse de clientes potencialmente pequeños.
Podrían tirar de mi FTP, pero ya lo estoy utilizando para descargas de "mis documentos" e intento hacerlo por otra via desconocida por mi y para mis investigaciones/pruebas.

Jose, voy a probar lo que me cuentas utilizando una tabla MyISAM, ya que como comentas, si que veo que una tabla normal como las que estoy utilizando, InnoDB, con solo de acceder a ver los registros con Heidi, y con pocos registros, se nota la lentitud de carga de registros en la parrilla.


Gracias.
Un Saludo,
Xevi.
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5706
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por jfgimenez »

XeviCOMAS escribió:Jose, voy a probar lo que me cuentas utilizando una tabla MyISAM, ya que como comentas, si que veo que una tabla normal como las que estoy utilizando, InnoDB, con solo de acceder a ver los registros con Heidi, y con pocos registros, se nota la lentitud de carga de registros en la parrilla.
Eso te va a pasar siempre, con InnoDB o con MyISAM. El problema de HeidiSql es que lee todas las filas de la tabla y te las muestra en un browse. Si tienes una tabla con 1000 fotos de 2MB cada una, tiene que leer 2GB desde el servidor y mostrartelos en el browse :-(

Por otro lado, en tu programa no pasa eso. Lo normal es tener unas pocas fotos por ficha (artículo, cliente, vehículo,...), pongamos entre 1 y 10 fotos. Si mostraras 10 fotos de 2MB directamente estarías leyendo 20MB, no 2GB. Y si además, en vez de leer las fotos usas miniaturas de 10KB cada una, estarías leyendo tan sólo 100KB

El problema que te comentaba no es por HeidiSql, sino por la BD en sí. Las tablas InnoDB tienen soporte completo de ACID, y eso consume recursos. Por otro lado, MyISAM no es ACID, y por tanto no soporta transacciones, pero a mi modo de ver no son necesarias en una gestión documental. Normalmente el usuario va a subir una a una las fotos que quiera, y si tiene un problema en un momento dado, no pasa nada porque en la ficha del artículo se hayan guardado 3 fotos y en la 4 le ha dado un error y tiene que volver a subirla
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
XeviCOMAS
Mensajes: 582
Registrado: Sab Mar 12, 2011 8:16 pm

Re: Cargar Imagen en SQLite y luego mostrarla

Mensaje por XeviCOMAS »

Jose,

MUCHAS GRACIAS por la aclaración.

Es tal como dices. No voy a traerme más de unas pocas fotos al momento de hacer la petición al SERVER.
Un Saludo,
Xevi.
Responder