Ayuda con Objeto Stream de ADO (Solucionado)

Re: Ayuda con Objeto Stream de ADO

Postby sjingo » Thu Jul 09, 2015 11:09 pm

Armando

Con las versiones que tu usas, si funciona. El problema es con versiones superiores por ejemplo con la que probé: FWH10.3 + Harbour 3.2 + BCC582 ya no me ha funcionado.

Para ver los datos puedes usar NAVICAT 8 para mysql. Al abrir la tabla puedes dar click en el botón "Image" de la barra de herramientas y podrás ver en la parte inferior el contenido del campo BLOB

Pero si en verdad quieres el código para leer, el proceso más o menos es el siguiente:
1. Se lee el contenido de la Tabla en un objeto stream
2. Con el contenido binario lo podemos pasar a una variable o un objeto TIMAGE
3. Yo lo que hago es lo contrario a la subida. Con el contenido ya puesto en el objeto Stream lo guardo en el disco y luego lo leo para colocarlo en un control IMAGE.

Te adjunto el código que lee la imagen, no he borrado nada. Hay código que ya ni me acuerdo para qué sirve. Así que si lo puedes minimizar que mejor.

La idea con este código es que cada imagen que se recupera de la base de datos lo guardo en una carpeta temporal en disco, son fotos de un vehículo. Por cada vehículo se crea una carpeta en función de su id y se graban las fotos allí, luego estas fotos de disco son mostradas en un objeto IMAGE.
Code: Select all  Expand view

//--------------------------------------------------------------
//cnombre : Nombre de la foto
METHOD LeerFoto(cnombre,oImg) CLASS TVehic
local nBookMark:=0
local sumatot:=0,cnom,ncod:="0"
local oRsFoto,Stream , ofoto,cFold,cfoto

//oRsV es el recordset que ya esta abierto y guarda toda la tabla
if !::oRsV:EOF .and. !::oRsV:BOF
    cFold:="V"+alltrim(str(::oRsV:Fields('cod_veh'):Value))
else
    return nil
endif

//Recuperamos del nombre pasado el codigo de la foto
cnom:=cfileNoExt(cnombre)
ncod:=substr(cnom,at("f",cnom)+1)

//Recordset para la foto grande
TRY
    oRsFoto := TOleAuto():New("adodb.recordset")
CATCH oError
    MsgStop( "No se pudo crear el recordset para la Foto !", CAR_VERSION)
    RETURN .f.
END

//Configuramos el recordset que me dovolvera una foto
oRsFoto:CursorLocation := adUseClient
oRsFoto:LockType := adLockOptimistic
oRsFoto:CursorType := adOpenKeyset//adOpenDynamic
oRsFoto:Source := "SELECT cod,foto,tipo FROM fotos_veh where cod ="+ nCod
****oRsFoto:ActiveConnection(oCon)

TRY
    oRsFoto:Open(oRsFoto:Source,oCon)
CATCH oError
    MsgStop( "No se pudo abrir la Tabla de la Foto!", car_version)
    ShowError(oError,oCon)
    RETURN .f.
END

TRY
    ::oStream := TOleAuto():New("adodb.Stream")
CATCH oError
    MsgStop( "No se pudo crear el Stream para leer la Foto !", CAR_VERSION)
END

// Especifica el tipo de datos ( binario )  
::oStream:Type := adTypeBinary

TRY
    ::oStream:Open()
CATCH oError
    MsgStop( "No se pudo establecer la conexion stream!", car_version)
    ShowError(oError,oCon)
    return .f.
END

if !lisDir("imgtmp")
    lMkDir("imgtmp")
endif
if !lisDir("imgtmp\" + cFold )
     lMkDir("
imgtmp\" + cFold )
endif

if !oRsFoto:EOF .and. !oRsFoto:BOF
    //Graba los datos en el objeto stream  
    IF oRsFoto:Fields('foto'):Value !=nil
        ::oStream:Write(oRsFoto:Fields('foto'):Value)
        cfoto:="
imgtmp\" + cFold+"fg"+alltrim(str(oRsFoto:Fields('cod'):Value)) + "." + alltrim(oRsFoto:Fields('tipo'):Value)
        if file(cfoto)
            ferase(cfoto)
        endif
        //Se graba un  archivo temporal  en disco
        ::oStream:SaveToFile(cfoto, adSaveCreateOverWrite)  
        if fsize(cfoto)>0  //aqui se debe cargar una imagen si no hay la precisa
            oImg:LoadBmp(cfoto)
        else
            oImg:LoadImage( "
shade" )
        endif
        oimg:Refresh()
    endif
endif

::oStream:Close()
oRsfoto:Close()

return .t.


Saludos
Marcelo Jingo
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: Ayuda con Objeto Stream de ADO

Postby Antonio Linares » Fri Jul 10, 2015 11:18 am

Marcelo,

Ya te he enviado el EXE construido a tu email

aguardo tus noticias
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41314
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Ayuda con Objeto Stream de ADO

Postby sjingo » Fri Jul 10, 2015 2:01 pm

Antonio

Lamentablemente, sigue igual, se obtiene el mismo error : "La operación en varios pasos generó errores. Compruebe los valores de estado (0x80040E21)".
Por si sirve de algo la versión de ado obtenido en oCon:Version es 6.3.

Decidí regresar a la versión anterior, y ya veré como arreglármelas con actualizaciones que había con la versión mas nueva que tenía.

Antonio gracias por tu tiempo. Cuando tenga más tiempo seguiré investigando este tema, ojalá alguien encuentre la solución y de seguro es una tontería.

Saludos
Marcelo Jingo
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: Ayuda con Objeto Stream de ADO

Postby Antonio Linares » Fri Jul 10, 2015 2:21 pm

Marcelo,

Yo creo que el problema viene de cambios realizados en Harbour, porque ahi no hay código de FWH
salvo que me equivoque.

Algo se ha modificado en el soporte de OLE que ha afectado a tu código.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41314
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Ayuda con Objeto Stream de ADO(Solucionado)

Postby sjingo » Sun Jul 12, 2015 12:09 am

...UF!!!

Después de buscar y buscar en internet, donde se comenta mucho sobre el mensaje "La operación en varios pasos generó errores. Compruebe los valores de estado (0x80040E21"), que en resumen se trata de un error que ocurre cuando se intenta asignar datos de tipos diferentes o cuando la longitud del campo de la tabla es más pequeño que lo que se quiere asignar, entre otros. Por lo tanto comencé a indagar por él lado de tipos de datos; y las respuestas las obtuve en este mismo foro, encontré este post que me ayudo mucho viewtopic.php?f=6&t=30559&hilit=base64 donde Carlos Vargas da una opción. No me funcionó de la forma exacta cómo allí se explica pero fue el camino a la solución.

Para subir las imágenes a mi tabla Mysql en un campo MEDIUMBLOB bastó con cambiar

Code: Select all  Expand view
oRsfoto:fields('foto'):Value := oStream:Read()

Por
Code: Select all  Expand view
oRsfoto:fields('foto'):Value := HB_STRTOHEX(oStream:Read())


Con esto se grabó correctamente en la Tabla MySQL. Ahora para leer la imagen creí que funcionaría igual haciendo lo opuesto con HB_HEXTOSTR(), por nop. Creo que son cosas de ADO, o de ODBC, o de Mysql ... no sé. Pero mirando en el visor en hexadecimal para campos blob que tiene NAVICAT, pude darme cuenta que los datos grabados estaban en el mismo formato de imagen y se lo podía visualizar en el visor de imagen de NAVICAT. Con esto pienso que Mysql antes de grabar transforma los datos que yo le envio con strtohex() a su forma original que es binario.

Para la lectura fue otro largo trajinar, porque no funcionó ni hb_strtohex(), ni hb_hextostr(), por lo que tuve que improvisar y se modificó la forma cómo lo hacía antes. Ahora ya no uso ADO Stream para grabar las fotos pequeñas a disco ni para ver la foto grande, sólo lo hago utilizando los datos del recordset directamente (Hoy me pregunto...por qué no lo hice así antes???).

Antes hacía esto:
Code: Select all  Expand view

                //Se carga en el objeto stream el valor del campo blob
        oStrp:Write(::oRsFoto:Fields('foto_p'):Value)
        //Se graba en un archivo temporal a disco mediante el método del objeto stream
        ::oStream:SaveToFile(cfile, adSaveCreateOverWrite)  
 

Pero ahora al hacer oStrp:Write se obtiene el mensaje: "argumentos incorrectos, fuera del intervalo permitido o en conflicto con otros "

Po lo que ya no busqué más y opté por no usar el objeto stream, la solución fue:
Code: Select all  Expand view

                //Con esto grabo el contenido del campo blob a un archivo en disco
                //cfile es el nombre de un archivo
            fichero:= fCreate( cfile )
        fWrite( fichero, ::oRsFoto:Fields('foto_p'):Value)
        fClose( fichero )

 


Por otro lado para mostrar la imagen, hacemos la consulta SQL para obtener un recordset y luego con la clase TIMAGE podemos visualizarla así:
Code: Select all  Expand view

oImg:LoadFromMemory(oRsFoto:Fields('foto'):Value)
oImg:Refresh()
 


Me dirán..."sólo para esto te demoraste tanto??", pues así pasa cuando sucede. Uno nunca sabe lo que nos depara las actualizaciones, y no sé si es cosa de FWH, de Harbour, de BCC582, de ADO, de MySQL o mía. Como decimos por aquí: "Dios averigüe y perdone" , je je je.

Gracias Antonio, Gracias Foro por contribuir a esta solución.
Marcelo Jingo
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: Ayuda con Objeto Stream de ADO (Solucionado)

Postby Armando » Sun Jul 12, 2015 2:12 am

Marcelo:

Excelente que hayas solucionado el problema, como decimos en algunas partes
de mi país "El que porfia mata venado, aunque a veces lo matan por porfiado" :D

Por cierto, parece que la clase TImage no funciona con imágenes PDF, conoces
alguna otra clase que me permita mostrar imágenes PDF?

Saludos
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
User avatar
Armando
 
Posts: 3061
Joined: Fri Oct 07, 2005 8:20 pm
Location: Toluca, México

Re: Ayuda con Objeto Stream de ADO (Solucionado)

Postby sjingo » Sun Jul 12, 2015 4:49 pm

Armando

Lamentablemente no tengo experiencia con Visores PDF, para generar un documento PDF lo que hago simplemente es usar cualquier driver estilo impresora como CUTEPDF, y enviar la impresión.

Saludos
Marcelo Jingo
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: Ayuda con Objeto Stream de ADO (Solucionado)

Postby Armando » Sun Jul 12, 2015 6:01 pm

Marcelo:

Gracias por la respuesta, para crear el PDF no tengo problema, mi problema es
mostrarlo en un dialogo o window, tal vez alguien más en el foro nos pueda apoyar

Saludos
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
User avatar
Armando
 
Posts: 3061
Joined: Fri Oct 07, 2005 8:20 pm
Location: Toluca, México

Re: Ayuda con Objeto Stream de ADO (Solucionado)

Postby sjingo » Sun Jul 12, 2015 10:58 pm

Armando

Si lo que quieres es sólo visualizar y nada más, podemos hacer uso de los recursos que casi todos los pcs tienen ya instalado: Explorer y Acrobat Reader, para ello podemos aprovechar ActiveX.

Aquí un ejemplo que lo armé al vuelo:
Code: Select all  Expand view

function VerPDF(cfile)  
    local ownd, oactivex,oFold
    default cfile:="C:\camisetas\SOFTWARE.pdf"
   
   DEFINE WINDOW oWnd TITLE "Archivo: "+alltrim(cfile)
    @5,25 FOLDER oFold size 100,500;
    PROMPT "Folder" ;
    PIXEL of oWnd
   
    oActiveX = TActiveX():New( oWnd, "Shell.Explorer.2" )
   //oWnd:oClient = oActiveX //ocupa toda la ventana
   oActiveX : Do("Navigate2",cfile)
   ACTIVATE WINDOW oWnd  maximized on init (oWnd:acontrols[2]:nHeight:=500,oWnd:acontrols[2]:nWidth:=600,oWnd:acontrols[2]:nTop:=25,oWnd:acontrols[2]:nLeft:=150)

RETUR NIL

Es sólo una idea inicial.

Saludos
Marcelo Jingo
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: Ayuda con Objeto Stream de ADO (Solucionado)

Postby Armando » Mon Jul 13, 2015 3:27 pm

Marcelo:

Muchas gracias por el código, voy a tirar por ahí.

Saludos
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
User avatar
Armando
 
Posts: 3061
Joined: Fri Oct 07, 2005 8:20 pm
Location: Toluca, México

Previous

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 84 guests