FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posts: 492
Joined: Wed Nov 16, 2005 12:03 PM
Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Mar 09, 2015 01:23 AM
// Almacena archivos de cualquier tipo en una tabla DBF o Gestor MySQL/SQLSERVER
// Juan navas jnavas@datapronet.com jnadaptapro@gmail.com
// Este programa fue extraido del sistema ERP AdaptaPro www.datapronet.com utiliza MYSQL
// Este ejemplo es mi aporte al foro de FiveWin, se puede utilizar en cualquier gestor de base de datos utilizando campos Memos
// El mecanismo es: A partir del Archivo BMP o Binario, Genera un archivo comprimido ZIP,texto mediante MIME, se fracciona en paginas y se almacena
// Para recuperarlo: Lee el contenido del memo, genera el archivo TEXTO, luego genera el archivo comprimido, finalmente se descomprime y genera el archivo nuevamente en la carpeta filerecover
// Requiere Libreria hbzlib.LIB
// Ejecucion desde la consola: savefilebmp <Nombre de Cualquier Archivo>
// Si no se indica el nombre del archivo, guardara el mismo binario y luego lo recupera en la carpeta filerecover
// Esta funcionalidad la hemos ìmplementado con campos BLOB y LONGTEXT en MYSQL.

#include "FiveWin.ch"

FUNCTION MAIN(cFile)
LOCAL aPag
LOCAL cBin :=Lower(GetModuleFileName( GetInstance() ))
LOCAL cFileDir:="FILES.DBF"
LOCAL cFilePag:="FILESPAG.DBF"
LOCAL aFile,I

DEFAULT cFile:=cBin

SET DELETE ON

IF !FILE(cFile)
MsgAlert("Archivo "+cFile+" no Existe")
RETURN NIL
ENDIF

ISTABLAS(cFileDir,cFilePag)

aFile:=DIRECTORY(cFile)
aPag :=GETPAGES(cFile)

IF Empty(aPag)
MsgAlert("Archivo no generó Paginado")
RETURN NIL
ENDIF

SELECT A
USE (cFileDir) EXCLU
GO TOP
// Remueve el COntenido
DELETE ALL FOR ALLTRIM(FIELD->FILE)=ALLTRIM(cFile)
PACK

APPEND BLANK
REPLACE FILE WITH cFile
REPLACE SIZE WITH aFile[1,2]
REPLACE PAGES WITH LEN(aPag)
COMMIT

// BROWSE()

SELECT B
USE (cFilePag) EXCLU
GO TOP
// Remueve el COntenido
DELETE ALL FOR ALLTRIM(FIELD->FILE)=ALLTRIM(cFile)
PACK

FOR I=1 TO LEN(aPag)
APPEND BLANK
REPLACE FILE WITH cFile
REPLACE PAGE WITH I
REPLACE MEMO WITH aPag[I]
COMMIT
NEXT I

// BROWSE()

CLOSE ALL

RECUPERAR(cFile)

RETURN NIL

FUNCTION cFileTemp(cExt)
LOCAL cFile:="tmp"+STRTRAN(LSTR(SECONDS()),".","")+cExt
RETURN cFile

FUNCTION lstr(nValue)
RETURN ALLTRIM(STR(nValue))


FUNCTION GETPAGES(cFileOrg)
LOCAL cFileZip :=cFileTemp(".ZIP")
LOCAL cFileMime:=cFileTemp(".TXT")
LOCAL aFiles :={},nSize:=0,oFile,cMemo:=""
LOCAL cBin :=Lower(cFilePath(GetModuleFileName( GetInstance() )))
LOCAL aPages:={},I,aTotal:={},nTotal:=0,lZip:=.F.
LOCAL aPag :={},nPage
LOCAL nFileMax :=(1024**4)*2 // Tamaño maximo permitido para almacenar, en paginado el limite esta en la capacidad de la tabla
LOCAL nPageSize:=(1024**2)/2 // Tamaño maximo de la Pagina, limite campo MEMO . Utilizado en MySQL para campos LONGTEXT

nPageSize:=65555 // Capacidad para tablas DBF

CursorWait()

IF !(":"$cFileOrg)
cFileOrg:=cBin+cFileOrg
ENDIF

cFileOrg :=Lower(cFileOrg)

AADD(aFiles,cFileOrg)

IF !(":"$cFileOrg)

MsgAlert("Es necesario Indicar la Ruta Completa del Archivo "+cFileOrg+CRLF+;
"Ejemplo "+cBin+"\docs\documento.doc")

RETURN 0

ENDIF

IF !FILE(cFileOrg)
MsgAlert("Archivo "+cFileOrg+" no Existe")
RETURN 0
ENDIF

IF UPPE(cFileExt(cFileOrg))="ZIP"
cFileZip:=cFileOrg
lZip :=.T.
ELSE
// El Archivo Original es Comprimido en Formato Zip
HB_ZipFile( cFileZip, aFiles, 9,,.T., NIL, .F., .F. )
ENDIF

// El Archivo MIME es Convertido en Formato TEXTO Segun Mime
FMimeEnc(cFileZip,cFileMime)

// Valida el Tamaño con el Archivo MIME
nSize:=DIRECTORY(cFileMime)[1,2]

IF nSize>nFileMax
MsgAlert("Archivo "+cFileMime+" Tamaño "+LSTR(nSize)+",Supera el Límite "+LSTR(nFileMax))
RETURN {}
ENDIF

// Determinamos las Páginas que seran empleadas

nPage :=MAX(INT(nSize/nPageSize),1)
aPages:={}

FOR I=1 TO nPage
AADD(aPages,{MIN(nPageSize,nSize)})
NEXT I

aTotal:=ATOTALES(aPages)

// Remanente de la Ultima Página
IF nSize>aTotal[1]
AADD(aPages,{nSize-aTotal[1]})
ENDIF

// Se Extra Pagina por Pagina del Arhivo MIME
oFile:=TFILE():New(cFileMime)

FOR I=1 TO LEN(aPages)
cMemo:=oFile:cGetStr( aPages[I,1] )
AADD(aPag,cMemo)
nTotal:=nTotal+LEN(cMemo)
NEXT I

oFile:End()

ferase(cFileMime)

IF !lZip
ferase(cFileZip)
ENDIF

RETURN aPag

FUNCTION ATOTALES(aData)
LOCAL aTotal,I,U

aTotal:=ARRAY(LEN(aData[1]))

Aeval( aTotal,{ |a,n| aTotal[n]:=0 })

FOR I=1 TO LEN(aData)

FOR U=1 TO LEN(aData[I])
aTotal[U]:=aTotal[U]+aData[I,U]
NEXT U

NEXT I

RETURN aTotal

PROCE ISTABLAS(cFileDir,cFilePag)
LOCAL aStruct:={}

IF FILE(cFileDir)
RETURN
ENDIF

AADD(aStruct,{"FILE", "C",250,0})
AADD(aStruct,{"SIZE", "N",12 ,0})
AADD(aStruct,{"PAGES","N",3 ,0})

dbcreate(cFileDir, aStruct)

aStruct:={}
AADD(aStruct,{"FILE","C",250,0}) // Archivo
AADD(aStruct,{"PAGE","N",4 ,0}) // Memo
AADD(aStruct,{"MEMO","M",0 ,0}) // Numero de la Pagina, es necesario el Orden para su Recuperación

dbcreate(cFilePag, aStruct)

RETURN

FUNCTION RECUPERAR(cFile)
LOCAL cFileDir:="FILES.DBF"
LOCAL cFilePag:="FILESPAG.DBF"
LOCAL cFileZip :=cFileTemp(".ZIP")
LOCAL cFileMime:=cFileTemp(".TXT")
LOCAL I,cDirOut:="filerecover\"

LOCAL aPag :={}
LOCAL oFile

lMkDir(cDirOut)

SELECT A
USE (cFileDir)
GO TOP
LOCATE FOR ALLTRIM(FIELD->FILE)=ALLTRIM(cFile)

IF !FOUND()
CLOSE ALL
MsgAlert("Archivo "+cFile+" no Encontrado en Tabla "+cFileDir)
RETURN .F.
ENDIF

SELECT B
USE (cFilePag) EXCLU
GO TOP
// Remueve el COntenido
LOCATE FOR ALLTRIM(FIELD->FILE)=ALLTRIM(cFile)

WHILE !EOF() .AND. ALLTRIM(FIELD->FILE)=ALLTRIM(cFile)
AADD(aPag,ALLTRIM(FIELD->MEMO))
SKIP
ENDDO

CLOSE ALL

// Desde DBF hacia MIME

oFile:=TFILE():New(cFileMime)
AEVAL(aPag,{|a,n| oFile:PutStr(a)})
oFile:End()

// De MIME a ZIP
ferase(cFileZip)
FMimeDec(cFileMime,cFileZip)
ferase(cFileMime)

HB_UNZIPFILE( cFileZip , {|| nil }, .t., NIL, cDirOut , NIL )
ferase(cFileZip)

MsgAlert("Archivo recuperado en carpeta "+cDirOut)

IF !cFileExt(cFile)="EXE"
SHELLEXECUTE(NIL,"open",cFile)
ENDIF

RETURN .T.
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Mar 09, 2015 04:51 AM

Juan,

gracias por compartirlo :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 492
Joined: Wed Nov 16, 2005 12:03 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Mar 09, 2015 05:26 AM

Antonio,
Muchas gracias espero que sea de utilidad, al principio tuve muchas dificultades para implementar en mi aplicacion el registro y recuperación de todo tipo de archivo.

Posts: 632
Joined: Thu Jan 19, 2006 10:45 AM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Mar 06, 2017 04:07 AM

Juan, Sencillamente una genialidad, es posible ponerse en contacto contigo. Tu correo no funciona.

Saludos



Andrés González desde Mallorca
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Mar 06, 2017 11:22 AM
Probably this very difficult approach was necessary during 16-bit clipper days about 20 years back.
Now all this totally not necessary.
We can simply assign file buffer value to the field.

Please try this sample which stores contents of a large file c:\fwh\lib\fiveh32.lib in the memo field of dbf file.

Code (fw): Select all Collapse
#include "fivewin.ch"

REQUEST DBFCDX

function Main()

   local cFile    := "c:\fwh\lib\fiveh32.lib" // file size is 5,480,0032

   DBCREATE( "contents.dbf", { { "FILENAME", 'C', 128, 0 }, { "CONTENTS", 'M', 8, 0 } }, "DBFCDX" )
   USE contents EXCLUSIVE

   DBAPPEND()
   FIELD->FILENAME   := cFile
   FIELD->CONTENTS   := MEMOREAD( cFile )

   DBCOMMIT()

   ? LEN( field->contents ), FILESIZE( cfile ) // --> 5480032, 5480032

   CLOSE CONTENTS

return nil


Same way even for storing large BLOB or TEXT data in MySql, MsSql or other databases, it can be done in one simple step.

MYSQL Example (using FWHMYSQL and can be tested with FWH 17.01):
Principle is the same for other libraries too.
Code (fw): Select all Collapse
#include "fivewin.ch"

function Main()

   // MYSQL
   local oCn, oRs
   local cFile    := "c:\fwh\lib\fiveh32.lib"

   oCn   := FW_DemoDB( 1 )
   // Note: It is important to set max_allowed_packet to sufficiently large value eg. 32MB

   if oCn:TableExists( "contents" )
      oCn:DropTable( "contents" )
   endif
   oCn:CreateTable( "contents", { { "filename", 'C', 128, 0 }, { "contents", 'm', 8, 0 } } )
   oCn:Insert( "contents", "filename,contents", { cFile, MEMOREAD( cFile ) } )

   oRs   := oCn:RowSet( "contents" )
   ? Len( oRs:contents ), FILESIZE( cfile ) // --> 5480032, 5480032

   oCn:Close()

return nil
Regards



G. N. Rao.

Hyderabad, India
Posts: 492
Joined: Wed Nov 16, 2005 12:03 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Mon Aug 27, 2018 08:27 PM
Andrés González wrote:Juan, Sencillamente una genialidad, es posible ponerse en contacto contigo. Tu correo no funciona.

Saludos
Puedes escribirme a jnavas@datapronet.com o adaptaprodrive@gmail.com
Posts: 107
Joined: Tue Sep 15, 2009 07:52 AM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Tue Aug 28, 2018 07:27 AM

Muy interesante tu método, sin embargo, te puedo decir que por mi larga experiencia manejando bases de datos con miles de imágenes y videos de todo tipo que he llegado a la conclusión de que es preferible lo siguiente:

  1. Un campo para almacenar el directorio donde el usuario almacena las imágenes (puede ser absoluto o relativo, recomiendo relativo o todo se vuelve una confusión total si el programa cambia de posición o si entregas un instalable; por ejemplo, con Innosetup http://jrsoftware.org/). Tipo texto longitud 120.
  2. Un campo en el que se almacena el tipo de imagen (BMP, JPG, etc) de longitud 4. Esto es optativo.
  3. Un campo tipo texto en el que almacenas el nombre de las imágenes. Yo lo hago así y me da muy buen resultado: Campo tipo texto de longitud 254 en el que el nombre máximo de las imágenes de limita a 8 caracteres sin espacios ni símbolos especiales y cada imagen se separa por un delimitador (yo uso ^). Esto me da la posibilidad de almacenar 254/9 (incluye el nombre del fichero y delimitador = 28 imágenes. Puedes jugar con la longitud permitida para el nombre de la imagen y/o incluir el tipo de imagen con el nombre.

El resultado es 3 campos de texto de un máximo de 120+4+254=378, sin blobs, memos, ni extras en la base de datos.

Emiliano Llano Díaz

Posts: 492
Joined: Wed Nov 16, 2005 12:03 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Tue Aug 28, 2018 11:06 AM

Emiliano
Saludos,

En nuestro caso, AdaptaPro es un sistema Open Source creado con HB + FW + MySQL, el proceso de actualización del sistema lo realizamos mediante el alojamiento de sus componentes en AdaptaPro Server, mas las personalizaciones creadas por los clientes. ha sido eficiente rápido y cómodo hacer las actualizaciones del sistema y distribución en los demás PC involucrados con la aplicación. Hemos erradicado la participación del personal técnico para la actualización del sistema.

Tambien para otros casos, utilizamos funcionalidades utilizar directorios y archivos donde no es necesario que estén almacenados en la BD

Posts: 880
Joined: Fri Jan 12, 2007 08:35 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Thu Feb 11, 2021 07:12 PM
Hola y como sacas el archivo para leerlo por decir una fotografía para presentarla en pantalla

estoy usando dbf

Saluditos :-)

Hello and how do you get the file to read it by saying a photograph to present it on screen

i am using dbf

Greetings: wink:


nageswaragunupudi wrote:Probably this very difficult approach was necessary during 16-bit clipper days about 20 years back.
Now all this totally not necessary.
We can simply assign file buffer value to the field.

Please try this sample which stores contents of a large file c:\fwh\lib\fiveh32.lib in the memo field of dbf file.

Code (fw): Select all Collapse
#include "fivewin.ch"

REQUEST DBFCDX

function Main()

   local cFile    := "c:\fwh\lib\fiveh32.lib" // file size is 5,480,0032

   DBCREATE( "contents.dbf", { { "FILENAME", 'C', 128, 0 }, { "CONTENTS", 'M', 8, 0 } }, "DBFCDX" )
   USE contents EXCLUSIVE

   DBAPPEND()
   FIELD->FILENAME   := cFile
   FIELD->CONTENTS   := MEMOREAD( cFile )

   DBCOMMIT()

   ? LEN( field->contents ), FILESIZE( cfile ) // --> 5480032, 5480032

   CLOSE CONTENTS

return nil


Same way even for storing large BLOB or TEXT data in MySql, MsSql or other databases, it can be done in one simple step.

MYSQL Example (using FWHMYSQL and can be tested with FWH 17.01):
Principle is the same for other libraries too.
Code (fw): Select all Collapse
#include "fivewin.ch"

function Main()

   // MYSQL
   local oCn, oRs
   local cFile    := "c:\fwh\lib\fiveh32.lib"

   oCn   := FW_DemoDB( 1 )
   // Note: It is important to set max_allowed_packet to sufficiently large value eg. 32MB

   if oCn:TableExists( "contents" )
      oCn:DropTable( "contents" )
   endif
   oCn:CreateTable( "contents", { { "filename", 'C', 128, 0 }, { "contents", 'm', 8, 0 } } )
   oCn:Insert( "contents", "filename,contents", { cFile, MEMOREAD( cFile ) } )

   oRs   := oCn:RowSet( "contents" )
   ? Len( oRs:contents ), FILESIZE( cfile ) // --> 5480032, 5480032

   oCn:Close()

return nil
Que es mejor que programar? creo que nada :)
Atropellada pero aqui ando :P

I love Fivewin

séʌǝɹ ןɐ ɐʇsǝ opunɯ ǝʇsǝ
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Thu Feb 11, 2021 10:28 PM
Saving image to DBF

Code (fw): Select all Collapse
ALIAS->MEMOFIELDNAME := MEMOREAD( cImageFile )


Display image in window / dialog:
Code (fw): Select all Collapse
@ r, c XIMAGE oImage SOURCE ALIAS->MEMOFIELDNAME SIZE w,h OF oDlg
Regards



G. N. Rao.

Hyderabad, India
Posts: 880
Joined: Fri Jan 12, 2007 08:35 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Fri Feb 12, 2021 12:09 AM
Thank you very much :-)

Regards :-)




nageswaragunupudi wrote:Saving image to DBF

Code (fw): Select all Collapse
ALIAS->MEMOFIELDNAME := MEMOREAD( cImageFile )


Display image in window / dialog:
Code (fw): Select all Collapse
@ r, c XIMAGE oImage SOURCE ALIAS->MEMOFIELDNAME SIZE w,h OF oDlg
Que es mejor que programar? creo que nada :)
Atropellada pero aqui ando :P

I love Fivewin

séʌǝɹ ןɐ ɐʇsǝ opunɯ ǝʇsǝ
Posts: 492
Joined: Wed Nov 16, 2005 12:03 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Tue Nov 07, 2023 03:14 PM
Puedes escribirme a jnadaptapro@gmail.com +58-4143000518
Posts: 1144
Joined: Mon Feb 05, 2007 07:15 PM
Re: Almacenar/Recuperar imagenes, binarios en Tablas DBF
Posted: Thu Nov 30, 2023 06:19 PM
jNavas
tus funciones funcionan de maravilla
gracias! :D
Cesar Cortes Cruz

SysCtrl Software

Mexico



' Sin +- FWH es mejor "

Continue the discussion