Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Lazarus, FreePascal, Kylix, etc. (https://www.clubdelphi.com/foros/forumdisplay.php?f=14)
-   -   cual es la mejor forma de trabajar con blob (https://www.clubdelphi.com/foros/showthread.php?t=80214)

anubis 10-09-2012 00:04:37

cual es la mejor forma de trabajar con blob
 
Hola amigos,

Ya estoy leyendo y guardando imagenes jpg en archivos blob de un bd, pero estoy limitado a los jpg.
Cargo el archivo jpg en un stream y al reves e incluso los imprimo con fortesreport.
La única pega que tiene es que cuando la imagen ocupa toda una hoja, en el fortesreport preview, se dificulta hacer zoom o subir y bajar el scroll.
Las imagenes ocupan sobre 300kb.
No se podria hacer lo mismo con imagenes png o bien con pdf (que seria lo idoneo)?

Ya estuve buscando lo mismo que use para el jpg pero en png pero no lo encuentro.

como lo trabajais vosotros?

saludos y gracias

Casimiro Notevi 10-09-2012 00:11:36

En un campo blob puedes guardar lo que quieras, ¿qué problema tienes?

anubis 10-09-2012 00:15:40

Si, gracias. Mas que nada el poder abrir un pdf en lazarus y luego pasarlo a un blob tal y como lo hago con jpg.

O bien un un png,

el problema es trabajar con formatos, verlos en pantalla por ejemplo y luego guardarloCon jpg no tengo problema, se me dificultan los otros formatos. Lease png o pdf.

Cita:

JPG:=TJPEGImage.Create;
if not OpenPictureDialog1.Execute then Exit;
jpg.LoadFromFile(OpenPictureDialog1.FileName);
Image1.Picture.Assign(JPG);
Stream := form1.ZQuery1.CreateBlobStream(form1.zquery1.FieldByName('factur'), bmWrite); // Asignamos el BLOB a un stream
jpg.SaveToStream(Stream); // y guardamos la imagen como JPEG (convertido), en el stream
Stream.Destroy;// liberamos
Esto es lo que uso.

saludos y gracias

Casimiro Notevi 10-09-2012 01:04:23

Lo que quieres es verlo "dentro" de tu programa o abrirlo con el programa predeterminado del sistema, ejemplo, si es un html que se abra el firefox, si es un gif que se abra el visor de imágenes, etc.
¿Eso es lo que quieres?

anubis 10-09-2012 01:07:23

con el jpg lo veo dentro de un timage,
un pdf o un png como lo puedo guardar en un blob desde dentro de mi programa?.

Casimiro Notevi 10-09-2012 02:02:18

¿Guardarlo?, tienes varias formas, pero simplificando mucho:
Código Delphi [-]
dataset.campoblob.loadfromfile('elficheroquesea.pdf');
Haz una búsqueda por clubdelphi, encontrarás código para hacerlo, es un tema muy repetido.

Es más, creo recordar que tú mismo preguntaste esto hace unos meses. Me parece que con sqlite.

anubis 10-09-2012 02:38:39

si, es cierto, pregunte, pero me faltaban esos detalles.

buscare en el foro, pero lo que me interesaba no es guardar sino poder abrir en mi aplicacion eso que se guarda, de ahi que use los jpg.

gracias

ecfisa 10-09-2012 03:19:29

Hola anubis.

No utilizo Lazarus pero ví que en varios sitios citaban a la librería [MuPDF], tal vez te sirva para lo que estas buscando.
Podes descargarlo de [aquí] (GNU Public License).

Saludos.

anubis 10-09-2012 03:52:49

Casimiro,
Ya resolvi una parte, la cuestion era que me empeñaba en usar el tjpegimage, cuando podia hacerlo como:

Código Delphi [-]
Image1.Picture.LoadFromStream(stream);
Asi me sirve para cualquier imagen soportada por timage.

lo unico que como png me ocupa 10 veces mas la imagen que con el jpg.

Como no voy a manipular imiagenes solo guardarlas en un blob y verlas.

Ahora me falta buscarle la forma con el pdf.

ecfisa, ya vi el componente pero no me sirve.

Lo que nose es si existe alguna forma de cargar el pdf de forma externa y pasarle el dato al stream para guardarlo?

Casimiro Notevi 10-09-2012 10:07:44

Cita:

Empezado por anubis (Mensaje 442568)
Lo que nose es si existe alguna forma de cargar el pdf de forma externa y pasarle el dato al stream para guardarlo?

Normalmente lo que yo hago es extraer del blob y guardar el fichero en un directorio temporal, luego ejecuto una llamada para abrirlo y es el propio windows el que se encarga de abrirlo con el programa predeterminado que tenga según del tipo de fichero que sea.
O sea, que lo abro "externamente" a mi programa.

anubis 11-09-2012 19:01:46

Gracias casimiro,

Ya estuve viendo el winexec, pero hace referencia a un archivo, lo que no entiendo como puedo, por ejemplo, es hacer una llamada para cargar una imagen en pdf (que lo abre con el acrobat p.e.) y de ahi pasarlo a un stream para guardarlo en un blob.
Porque me imagino que el proceso inverso, leer de un blob y pasarlo para visualizarlo con el acrobat.

Componentes para lazarus de pdf no he visto salvo powerpdf, pero solo para crear y en mi caso no he logrado que funcione bien.:(

gracias de nuevo.

Casimiro Notevi 11-09-2012 19:25:38

Tú sólo has de decirle al sistema que lo abra, él sabrá con qué abrirlo.
Normalmente con ShellExecute, si mal no recuerdo.
Haz una búsqueda por esa palabra en los foros, encontrarás código de ejemplo.

mightydragonlor 11-09-2012 20:17:48

TProcess para que sea multiplataforma con Lazarus.

Casimiro Notevi 11-09-2012 20:38:40

Cita:

Empezado por mightydragonlor (Mensaje 442807)
TProcess para que sea multiplataforma con Lazarus.

¿La función como se llama así?

mightydragonlor 11-09-2012 21:23:31

no, TProcess es una clase que permite ejecutar cualquier programa externo.
http://www.freepascal.org/docs-html/.../tprocess.html

roman 11-09-2012 21:33:28

Pero ShellExecute sirve también para abrir el programa asociado al archivo que se le pasa. ¿TProcess también?

// Saludos

mightydragonlor 11-09-2012 21:45:57

El ShellExecute sólo sirve para Windows, TProcess funciona con Win2, Linux y MacOS, pero depende mas de lo que quieras abrir y el como lo quieres abrir, es decir, puedes ejecutar excel y pasarle como parámetro la ruta del archivo con TProcess y funciona, ahora, si no sabes que ruta o que programa abre que, se puede usar la función OpenDocument, sólo debes poner en uses LCLIntf y LCLProc, y abrirá el documento con el programa asignado en el S.O.

roman 11-09-2012 21:51:11

Cita:

Empezado por mightydragonlor
si no sabes que ruta o que programa abre que, se puede usar la función OpenDocument

Pues sí, es que esta funcionalidad es la que planteaba Casimiro desde un principio.

// Saludos

rretamar 11-09-2012 23:28:09

Si son archivos muy grandes (y muchos) cuidadín con guardarlos en la base de datos. No sólo por el tamaño que alcanzará el archivo, sino porque si se daña la base de datos existe la posibilidad de que no se pueda recuperar la información. Cuesta un poco más (algunas líneas de código adicionales) pero en lo particular a los archivos de ese tipo (imágenes, video, audio) prefiero almacenarlos fuera de la base de datos, y colocando un campo donde almaceno la ubicación del archivo externo.

A lo mejor es que soy medio paranoico con la "pérdida de datos".

Como decía un profesor:

-"¿ Podés usar una consulta SQL que te de como resultado las morochas o las rubias en el campo de imágenes de la base de datos ?". -"!!! No !!!"...-"¿ Entonces para qué almacenas imágenes en una base de datos ?". :D

Casimiro Notevi 12-09-2012 00:52:15

Cita:

Empezado por rretamar (Mensaje 442849)
Como decía un profesor:
-"¿ Podés usar una consulta SQL que te de como resultado las morochas o las rubias en el campo de imágenes de la base de datos ?". -"!!! No !!!"...-"¿ Entonces para qué almacenas imágenes en una base de datos ?". :D

Pues si no guardas las imágenes... tampoco puedes saberlo ;)

No sé qué BD está usando, pero en los últimos 2012-1998=14 años nunca he tenido ningún problema de ese tipo con firebird y con BDs de muchos gigas.

roman 12-09-2012 16:32:16

Pues además, ese argumento invalida todos los blobs, no sólo las imágenes.

// Saludos

rretamar 12-09-2012 17:02:51

Cita:

Empezado por roman (Mensaje 442892)
Pues además, ese argumento invalida todos los blobs, no sólo las imágenes.

// Saludos

Me refería a casos donde:

1) La cantidad de archivos a incluir en la base de datos sea muy grande (no hablo de decenas, sino de muchos miles por mes).

2) Los archivos sean de gran tamaño.

En esos dos casos me plantearía si realmente tiene sentido almacenarlos directamente dentro de un campo blob. Igual, insisto, es que soy un poco (¿ un poco ? :p ) paranoico con eso de la pérdida de datos, los riesgos, las copias de seguridad y todo eso.

Respondiendo a Casimiro: si bien no me dedico profesionalmente al desarrollo de software (es una actividad secundaria que tengo), las bases de datos que he usado son Firebird y SQLite.

Sobre las rubias, morochas o pelirrojas...al ritmo con que avanza todo (ver las funciones de reconocimiento de rostros que traen sitios como Google o Facebook...o muchas cámaras digitales) dentro de poco el estándar ANSI SQL incorporará cosas como:

Select Nombre, Edad, Estado_Civil, Foto From Empleados Where Foto = (Morochas Or Pelirrojas)

Será la era en que CUPIDO use una base de datos SQL para sus "trabajos".

roman 12-09-2012 17:21:25

Cita:

Empezado por rretamar (Mensaje 442898)
Select Nombre, Edad, Estado_Civil, Foto From Empleados Where Foto = (Morochas Or Pelirrojas)

Sería mejor así:

Código SQL [-]
Select Nombre, Edad, Estado_Civil, Foto From Empleados Where Foto like :foto

Y proveemos la foto similar a la que queremos encontrar. O, ya por lo menos:

Código SQL [-]
Select Nombre, Edad, Estado_Civil, Foto From Empleados Where Foto between :menor_expectativa and :mayorexpectativa

:D

// Saludos

anubis 13-09-2012 00:38:08

Si es correcto, si lo pones en otra base de datos y se perdieran los blob, por lo menos el resto de los datos quedarian intactos, aunque tambien ha habido corrupcion de datos en firebird.

De todas formas, nose porque no hay un componente para leer pdf en lazarus. Segun habeis dicho en otros post, de excel es complicado que lo hubiera porque excel es privativo, pero esta libreoffice que tambien los lee, pdf seria privativo porqque es de acrobat, pero linux tambien tiene okular por ejemplo.

De ahi, siendo un componente que se suele usar, el pdf, y el excel (de excel si hay pero reducido), no lo haya para lazarus, teniendo en cuenta que hay bastantes componentes, lease el codetyphon que trae muchos.

lo del tprocess y el shellexecute los tengo que ver a fondo porque de momento no me entero muy bien como paso un pdf a un stream y de ahi a un blob y viceversa, pero seguire intentando.

Saludos

Casimiro Notevi 13-09-2012 00:39:49

Ahora sí que no he entendido, ¿estás buscando un componente para leer archivos pdf?

mightydragonlor 13-09-2012 01:16:37

Cita:

Empezado por anubis (Mensaje 442957)
Si es correcto, si lo pones en otra base de datos y se perdieran los blob, por lo menos el resto de los datos quedarian intactos, aunque tambien ha habido corrupcion de datos en firebird.

De todas formas, nose porque no hay un componente para leer pdf en lazarus. Segun habeis dicho en otros post, de excel es complicado que lo hubiera porque excel es privativo, pero esta libreoffice que tambien los lee, pdf seria privativo porqque es de acrobat, pero linux tambien tiene okular por ejemplo.

De ahi, siendo un componente que se suele usar, el pdf, y el excel (de excel si hay pero reducido), no lo haya para lazarus, teniendo en cuenta que hay bastantes componentes, lease el codetyphon que trae muchos.

lo del tprocess y el shellexecute los tengo que ver a fondo porque de momento no me entero muy bien como paso un pdf a un stream y de ahi a un blob y viceversa, pero seguire intentando.

Saludos

Pos de excel si hay y se llama TSpreadsheet, para leer archivos de pdf no conozco.

anubis 13-09-2012 02:52:10

Casimiro, lo que propones puede ser una solucion, pero si existiera un componente como el timage para hacer lo mismo con los pdf estaria bien, pero no lo hay, el shellexecute y el tprocess todavia los estoy digeriendo ;), porque todavia no veo como abrir y pasar lo que he abierto (dentro de un tprocess o shellexecute, que todavia esta complicado) a un stream y de ahi guardarlo (el stream ya lo uso con las imagenes).

mightydragonlor, si, ese componente lo he usado, pero esta muy limitado, por ejemplo, combinar celdas no se puede, y determinadas fórmulas tampoco.

Casimiro Notevi 13-09-2012 09:39:26

Esto abre la imagen con el programa que tenga asociado windows para hacerlo:

Código Delphi [-]
ShellExecute(0, 'open', 'c:\Windows\System32\rundll32.exe', 'c:\Windows\System32\shimgvw.dll,ImageView_Fullscreen c:\imagen.jpg', nil, SW_NORMAL);

Antes tienes que guardar la imagen en disco, claro.

anubis 13-09-2012 14:40:08

Gracias casimiro por perder un poco de tu tiempo ;).

Creo ver por donde vas.
Si entendí bien con los campos blob, pueden contener cualquier cosa, en este caso, imagenes, pero los guarda en formato binario, y ya es cuestion de encontrar el componente que sea capaz de leerlos, en este caso timage.

Eso funciona bien, pero veo que en el caso del shellexecute, necesitas a fuerza una ruta y un nombre de archivo, cosa que en el blob no tengo.

si es asi verdad?

Casimiro Notevi 13-09-2012 15:03:50

Cita:

Empezado por anubis (Mensaje 443003)
Gracias casimiro por perder un poco de tu tiempo ;).
Creo ver por donde vas.
Si entendí bien con los campos blob, pueden contener cualquier cosa, en este caso, imagenes, pero los guarda en formato binario, y ya es cuestion de encontrar el componente que sea capaz de leerlos, en este caso timage.
Eso funciona bien, pero veo que en el caso del shellexecute, necesitas a fuerza una ruta y un nombre de archivo, cosa que en el blob no tengo.
si es asi verdad?

Claro, un campo BLOB almacena lo que quieras.
Cuando se tiene un campo de ese tipo en el que se almacena "cualquier cosa" entonces es necesario tener otro campo que diga qué es, para poder guardarlo en disco y luego abrirlo, ejemplo:

Código SQL [-]
create table tbAlmacen (
  id integer not null,
  descripcion varchar(64),
  tipo varchar(16),
  contenido blob sub_type 0,
  primary key (id)
)
Y el contenido sería algo así:

Código:

1___Tutorial instalación Ubuntu___PDF___%$·/"%&%"%$·"%"··$
2___Foto de nubes_________________PNG___(&/$&$%&$·%$·"%$
3___Listado precios de NAS________TXT___Listado de precios de
4___Foto de moto__________________JPG___(/(//%&·&%$&%"·$

Así puedes extraer el que te interese a un directorio temporal, le pones un nombre temporal y la extensión que has guardado a la hora de crearlo (lo extraes del propio nombre del archivo cuando lo guardaste) y después lo abres como se ha indicado anteriormente.

anubis 21-09-2012 16:23:44

Hola de nuevo,

Estaba probando lo que me Casimiro comentaba pero no me sale,
Código Delphi [-]
VAR
  STREAM:TSTREAM;
  A:TFILESTREAM;
begin
  Stream := ZQuery1.CreateBlobStream(zquery1.FieldByName('facturA'), bmREAD); // Asignamos el BLOB a un stream
STREAM.Position:=0;                         

  A:=TFILESTREAM.Create('D:\PADILLA.JPG',fmCreate);
   A.CopyFrom(STREAM,STREAM.Size);

No se si va por ahi, el pasar el archivo a un directorio temporal, o hay otra forma de hacerlo.:confused:

saludos y gracias

Casimiro Notevi 21-09-2012 16:34:15

Es que no tienes que crear ningún stream, del campo blob lo guardas directamente en el disco, para eso guardamos el tipo de fichero que es.
Código Delphi [-]
undataset.campoblob.savetofile('loquesea.xxx');

anubis 21-09-2012 17:02:39

si, gracias, tienes razon se podria hacer asi pero intento hacer esto:

Código Delphi [-]
zquery1.FieldByName('factura')
pero no me deja ponerle asblob ni savetofile.

Seguramente sera una tonteria

Casimiro Notevi 21-09-2012 17:39:29

Cita:

Empezado por anubis (Mensaje 443839)
si, gracias, tienes razon se podria hacer asi

¿Pero así te funciona?

anubis 21-09-2012 17:58:20

Mas que nada porque no me deja poner mas porque no lo hay, nose cual es la instruccion para que haga l oque me dices.

gracias de nuevo

mightydragonlor 21-09-2012 18:19:33

lo que dice casimiro no es un método de un FieldbyName('xxxxx').AsBlob, sino mas bien que al crear el DataSet, donde especifica que campo y que tipo de dato es, un TField si no estoy mal, pero esto no serviría para Dataset´s creados en tiempo de ejecución.

anubis 22-09-2012 04:23:51

Buenas amigos,

Aplicando vuestros sabios consejos al final he conseguido algo de lo que pretendía, sacar una imagen de un blob y guardarlo en un archivo para poder visualizarlo externamente.
Lo saqué de otro post.
Código Delphi [-]
 PROCEDURE TFORM1.LEERBLOB;
 VAR
   BLOB:TSTREAM;
   BEGIN
     blob := zquery1.CreateBlobStream(zquery1.FieldByName('factura'), bmRead);
   try
    blob.Seek(0, soFromBeginning);
    with TFileStream.Create('PRUEBA.jpg', fmCreate) do
      try
        CopyFrom(blob, blob.Size)
      finally
        Free
      end;
  finally
    blob.Free
   end;
  ShellExecute(0, 'open', PChar('prueba.jpg'), Nil,Nil, SW_SHOWNORMAL);
  END;

En este caso, tenia almancenadas solo imagenes jpg, pero cambiando un poco las cosas posteriormente, podre meter finalmente los pdf o lo que sea (tal como decia casimiro, gracias).

El método que comentabais de no usar intermediarios sino guardarlo directamente no he sido capaz de realizarlo:(, pero este sirve.

Me falta ahora implementarlo al reves, que no tiene que ser dificil ;)

La última cuestión es relacionado con el shellexecute, funcionar funciona estupendamente, aunque me gustaba más el tprocess, tal y como he visto, pero le falla 1 punto:

- Se necesita un ejecutable a fuerza (si, opendocument funciona pero no es ni mas ni menos que un shellexecute).

Y la ventaja que si he visto es que si abres el archivo con tprocess, hasta que no cierras la aplicacion externa no vuelves a tu programa.

Entonces, de que otra forma se le puede decir a tprocess que abra un archivo, por ejemplo, un pdf, con el programa determinado en la máquina que lo estas corriendo.

saludos y gracias

ElMug 22-09-2012 11:49:23

Puedes guardar lo que sea en un BLOB, pero MOSTRARLO como lo que es, en una aplicacion, solo lo podras hacer si tienes el driver especifico para el caso.

El asunto es que hay infinidad de formatos de archivos, y algunos no son necesariamente abiertos, o standard, al grado de que solo se abren, en lo practico, con su aplicacion, o aplicaciones, para el caso.

Para PDF necesitas controles de Adobe, que son gratuitos.

Una columna para todo tipo de BLOBS, por ejemplo, lo mas probable es que no sea algo muy practico. En mi opinion, tendria que estar muy justificado, por cuestiones practicas.

Una de esas cuestiones podria ser la magnitud de la data, aparte de el poder "mostrar" o USAR el BLOB directo de la aplicacion.

Mi uso de BLOBS se limita a imagenes, y como hay muchos formatos, he decidido limitar a JPEG y .bmp, por ejemplo (maximo dos TIPOS de blobs en una misma columna), con codigo para filtrar el almacenamiento, y codigo para descifrar el tipo y mostrarlas en la aplicacion. Y aun asi, lo practico es que las imagenes no sean de mucha resolucion, para que el tamaño del BLOB no afecte la fluidez del uso de ellos.

Si tu interes es en PDF, es recomedable que te aboques a resolver ESE caso en especifico, antes que tratar de generalizar.

Casimiro Notevi 22-09-2012 12:40:17

En un BLOB puedes guardar lo que quieras, sin ningún problema, es simplemente una "cadena" de caracteres. Da igual si es una imagen, un pdf, un video, un texto, un mp3, un ejecutable, una base de datos completa, etc. cualquier cosa. La base de datos no va a hacer ningún tipo de control sobre lo que se guarda, le da igual.
Si se extrae lo almacenado en un campo blob y se guarda en disco, si intentamos abrirlo entonces el sistema operativo usará el programa que tenga predeterminado para el mismo, si lo tiene, y en caso contrario dirá que no puede abrirlo. No es ningún problema.
En mi extrabajo tenemos un módulo de seguimientos (para clientes/proveedores/artículos/vendedores/documentos/etc.) donde se almacena "cualquier cosa", y puede ser luego visionada, extraída, impresa, reproducida, etc. según el tipo de fichero del que se trate.
Por ejemplo, en la ficha de proveedores, en su apartado "Seguimientos" se pueden almacenar sus documentos en formato pdf, fotos de los representantes de la empresa, una imagen escaneada de un periódico donde hablan sobre esa empresa y que conviene tenerlo a mano, etc. cualquier cosa que sirva para tener información sobre ese proveedor.
Para este caso en concreto se usa una base de datos externa donde se almacena todo lo concerniente a "Seguimientos", para no recargar la base de datos principal de la gestión comercial.
O sea, que no hay que "restringirse" a uno o dos formatos de imágenes o documentos pdf. Que si hace falta almacenar más cosas, se almacenan y no pasa nada.
También (y aquí volvemos al eterno debate) se puede almacenar en directorios externos con sus pros y sus contras, que creo que no es necesario recordar.

Lo de almacenarlo en una base de datos aparte es porque ya llegan a tamaños bastante considerables, deben rondar ya los 50 gigas de media. Y no es necesario estar haciendo backup todos los días de esa información.

ElMug 22-09-2012 13:27:38

Si, Casimiro, pero si para verlos hay que vaciar el Blob de la base de datos a un archivo temporal, y da casi lo mismo que tener ya los archivos originales en un folder, y almacenar en la base de datos solo la ubicacion del archivo.

De esa manera, la base de datos es mas ligera.

Lo unico es que la base de datos NO ES portatil. Pero si la base es fija, y los Blobs son grandes, pues en lo personal optaria por solo usar apuntadores a las ubicaciones.

Ademas no me es pausible que se guarde "todo tipo de Blobs", pues ya que Blobs pueden ser hasta peliculas, musica, etc, a la cual no le veo caso que se almacenen en base de datos, si no es que sea ESE el uso especifico.

Cada caso y uso, sin embargo, se debe de basar en lo que mas conviene.


La franja horaria es GMT +2. Ahora son las 18:02:35.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi