no, aca guarda ell nombre del archivo, y el contenido binario convertido a hexadecimal.
para recuperarlo hace falta tomar el hexadecimal, y pasarlo nuevamente a binario.
salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
no, aca guarda ell nombre del archivo, y el contenido binario convertido a hexadecimal.
para recuperarlo hace falta tomar el hexadecimal, y pasarlo nuevamente a binario.
salu2
cFoto := ".\Autos\corolla1.jpg"
? FILE( cFoto ) // devuelve .t. si existe
oApp:oServer:Query("INSERT INTO imagenes (id,nombre) VALUES ('1','" + StrToHex(cFoto) + "')")
? "pausa agrego" // en esta pausa renombro la imagen por corolla11.jpg. para veri si la guarda la imagen en la tabla
oQry := oApp:oServer:Query("SELECT * FROM imagenes")
oImage := HexToStr( Alltrim(oQry:FieldGet("nombre")) ) // se supone que recupero la imagen
oQry:End()
DEFINE DIALOG oDlg FROM 0, 0 TO 22, 60
@ 0, 0 IMAGE oImage SIZE 150, 150 OF oDlg ADJUST // no me muestra la imagen
@ 6, 28 BUTTON "Exit" SIZE 50, 10 OF oDlg ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTER cFotoName := ".\autos\corolla1.jpg"
IF !File( cFotoName )
MsgAlert( "No se encuentra archivo de imagen." )
RETURN
ELSE
cFotoHexa := StrToHex( FileStr( cFotoName ) )
IF len( cFotoHexa ) = 0
MsgAlert( "Falla en lectura ó conversion de archivo a hexadecimal." )
RETURN
ENDIF
ENDIF
cInsertSql := "INSERT INTO imagenes (id,nombre,archivo) VALUES (%1,%2,%3)"
cInsertSql := StrFormat( cInsertSql, Var2Sql( "1" ), Var2Sql( cFileNoPath( cFotoName ), Var2Sql( cFotoHexa ) ) )
oApp:oServer:Query( cInsertSql )
cFotoName := ""
cFotoHexa := ""
cInsertSql := ""
oQry := oApp:oServer:Query("SELECT * FROM imagenes WHERE id='1'")
IF oQry:RecCount() == 0
MsgAlert( "No se encontro registro conicidente en el consulta." )
RETURN
ENDIF
cFotoName := oQry:FieldGet("nombre")
cFotoFile := HexToStr( oQry:FieldGet("archivo") )
oQry:End()
DEFINE DIALOG oDlg FROM 0, 0 TO 22, 60
@ 0, 0 IMAGE oImage SIZE 150, 150 OF oDlg ADJUST
@ 6, 28 BUTTON "Exit" SIZE 50, 10 OF oDlg ACTION oDlg:End()
ACTIVATE DIALOG oDlg ON INIT ( oImagen:LoadFromMemory( cFotoFile ) ) /*al inicio carga desde memoria la imagen al control*/
/*
MakeDir( "temp" )
IF StrFile( cFotoFile, "temp\" + cFotoName ) > 0
MsgAlert("Archivo guardado")
ENDIF
*/
/*------------------------------------------------------------------*/
TODO: val scape for string value pending.
FUNCTION Var2Str( xValue )
LOCAL cValue := "''"
DO CASE
CASE HB_IsString( xValue )
cValue := "'" + xValue + "'"
CASE HB_IsNumeric( xValue )
cValue := AllTrim( CStr( xValue ) )
CASE HB_IsLogical( xValue )
cValue := IIf( xValue, '1', '0' )
CASE HB_IsDate( xValue )
cValue := "'" + DToC( xValue ) + "'"
CASE HB_IsDateTime( xValue )
cValue := "'" + TToC( xValue ) + "'"
ENDCASE
RETURN cValue
/*------------------------------------------------------------------*/Carlos,
agregando el FileStr() y el LoadFromMemory, funciona, pero note algo.
mi imagen pesa 19.6kb y almacenada ocupa 40k, imagenes grandes no me almacena, pesa 1.94Mb, imagino que debe ser alguna configuracion del mysql para almacenar imagenes de ese tamaño.
y puede estar por aqui,
max_allowed_packet
por defualt es 1M, sera cuestion de cambiar y probar.
Gracias
Saludos
SET GLOBAL max_allowed_packet=16777216; or SET SESSION max_allowed_packet=16777216;
oServer:Execute("SET SESSION max_allowed_packet=16777216;") //permitiria archivos de 16MB (8MB en realidad ya que al pasar a hex se duplica )Paco,
yo tuve el mismo problema y lo solucioné con un consejo de Carlos, al usar :
uData := FileStr( cFile )
oServer:Insert( "mfile", { "nombre", "dato" }, { cFileNoPath(cFile), HB_Base64Encode( uData, LEN( uData ) ) } )
y:
uData:= HB_Base64Decode( oTmp:dato )
StrFile( uData, cFile )
Shellexecute( , "open", cFile )
o sea en vez de usar strhexa(), usar base64...()
Espero te sirva.
Salu2, Ariel.
HB_Base64Encode y HB_Base64Decode son funciones similares a las StrToHex y HexToStr, ya que toman valores binarios y lo trasforman a una cadena de caracteres que pueden ser trasmitidos y manipulados de mejor forma.
en este caso al pasa a hexadecimal duplica el tamaño, HB_Base64Encode lo incrementa en dos tercios, es mas eficiente en cuanto a tamaño, pero me parece que el hexadecimal es mas rapido.
cuestion de gusto.
Ok, enterado y gracias
Saludos
leandro wrote:Mr Rao y Carlos... Como siempre muy gentiles. Gracias por las respuesta.
Voy a analizar y probar todas las ideas que me han dado y al rato les comento los resultados.
Carlos:
Te cuento que definí la columna de tipo bytea.
Voy a probar con las funciones que mencionas y te comento
De nuevo gracias por las respuestas.
Leandro,
Esta funcionalidad la he implementado con MYSQL SQLSERVER y DBF, he logrado almacenar binarios y diversos tipos de datos
// Almacena archivos de cualquier tipo en una tabla DBF o Gestor MySQL/SQLSERVER
// Juan navas <!-- e --><a href="mailto:jnavas@datapronet.com">jnavas@datapronet.com</a><!-- e --> <!-- e --><a href="mailto:jnadaptapro@gmail.com">jnadaptapro@gmail.com</a><!-- e -->
// Este programa fue extraido del sistema ERP AdaptaPro <!-- w --><a class="postlink" href="http://www.datapronet.com">www.datapronet.com</a><!-- w --> 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.
Saludos
Juan Navas
<!-- w --><a class="postlink" href="http://www.datapronet.com">www.datapronet.com</a><!-- w -->
<!-- w --><a class="postlink" href="http://www.adaptapro.com">www.adaptapro.com</a><!-- w -->
<!-- e --><a href="mailto:jnavas@adaptapro.com">jnavas@adaptapro.com</a><!-- e -->
User avatar
jnavas
Posts: 188
Joined: Wed Nov 16, 2005 12:03 pm
Location: Caracas - Venezuela
TopBuenas tardes para todos....
Revisando el post, que coloco Francisco Horta, me di cuenta que efectivamente se estaba almacenando la ruta del archivo, mas no el archivo como tal.
Carlos voy a probar tu código y te comento.
Muchas gracias por el dato.