Hola, estoy trabajando con xml y necesito la libreria que contiene el hbtip para xharbour,,, donde la puedo encontrar
Saludos
Hola, estoy trabajando con xml y necesito la libreria que contiene el hbtip para xharbour,,, donde la puedo encontrar
Saludos
Estimado/a elmoiquique,
La librería hbtip (clases TIP: HTTP, SMTP, POP3, FTP...) es una contribución del proyecto Harbour, no de xHarbour. Su código fuente está aquí: https://github.com/harbour/core/tree/ma ... trib/hbtip
Ojo con dos cosas, que no he podido comprobar con xHarbour:
Para ayudarte mejor, dinos qué necesitas hacer con el XML (leer, escribir, descargarlo por HTTP...) y qué versión de xHarbour y qué compilador usas.
Un saludo,
FiveTech AI
necesito descargar un xml, que trae un documento pdf
version xharbour 24.09
compilador borland 7.70
Estimado/a elmoiquique,
Gracias por los datos. Para descargar el XML por HTTP/HTTPS en Windows sin depender de hbtip, una opción que funciona con cualquier versión de xHarbour y Borland es usar el objeto COM WinHttp de Windows. Ejemplo mío, sin probar, hay que adaptar la URL y las cabeceras que pida el servicio:
Code: Select all | Expand
FUNCTION DescargaXml( cUrl )
LOCAL oHttp, cXml := ""
oHttp := CreateObject( "WinHttp.WinHttpRequest.5.1" )
oHttp:Open( "GET", cUrl, .F. )
oHttp:Send()
IF oHttp:Status == 200
cXml := oHttp:ResponseText
ENDIF
RETURN cXml
Si el servicio exige usuario o clave, o es un POST, indícanoslo y se adapta.
Sobre el PDF: lo normal es que vaya dentro del XML codificado en base64, en cuyo caso primero hay que extraer ese nodo del XML y luego decodificarlo y guardarlo como archivo .pdf. Si nos pegas un trozo del XML (sin datos privados, y recortando el contenido del PDF) vemos cómo extraerlo.
Un saludo,
FiveTech AI
------=_Part_6863_601077142.1788989456375
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: 8bit
Content-ID: <soapPart>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Header xmlns:work="http://bea.com/2004/06/soap/workarea/"><cl:token xmlns:cl="cl.zofri.sve">302fbb06042b38677--07809839-e4-8-8081-9a4f db01-c487-9:94d31c40f92:1a454-05fbb26740bf8278-60-8-9630-949898-8a-0a6f9d90 -741769892d:1e43f7201f4:4</cl:token><cl:respuesta xmlns:cl="cl.zofri.sve"><java:resCodigo xmlns:java="java:cl.zofri.sve.utl.bo">0</java:resCodigo><java:resMensaje xmlns:java="java:cl.zofri.sve.utl.bo">Se ejecutó correctamente el servicio. </java:resMensaje><java:resSeveridad xmlns:java="java:cl.zofri.sve.utl.bo">O</java:resSeveridad></cl:respuesta><work:WorkContext xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility" xmlns:work="http://bea.com/2004/06/soap/workarea/"><java class="java.beans.XMLDecoder">
<string>weblogic.app.sveParametrosEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string>weblogic.app.sveCoexistenciaEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string>weblogic.app.svePerfilacionEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.2</string>
<string>weblogic.app.sveProcDocEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.64.1</string>
<string>weblogic.app.knaEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string>weblogic.app.sveAplicacionEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string>weblogic.app.sveReglasEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string>weblogic.app.sveAuditoriaEAR</string>
<int>214</int>
<string>weblogic.workarea.StringWorkContext</string>
<string>1.61.0</string>
<string/>
</java></work:WorkContext></env:Header><env:Body><m:emisionDocumentoResponse xmlns:m="http://cl/zofri/sve/prd/wsn"><m:return><Include xmlns="http://www.w3.org/2004/08/xop/include" href="cid:return=21a7c53a-5a11-41f8-a730-d6c0e2cead93@http://cl/zofri/sve/prd/wsn"/></m:retur ... v:Envelope>
Estimado/a elmoiquique,
Gracias por pegar la respuesta. Corrijo lo que te dije antes: el PDF no va en base64 dentro del XML. Es una respuesta SOAP con adjuntos MTOM/XOP (multipart/related): la primera parte es el XML y en ella solo hay una referencia al adjunto:
Code: Select all | Expand
<Include xmlns="http://www.w3.org/2004/08/xop/include" href="cid:return=..."/>
El PDF viene en otra parte del mismo mensaje, en binario, después de la siguiente línea "------=Part..." (con su propio Content-Type y Content-ID). Por eso no se puede tratar la respuesta como texto.
Camino sugerido, sin probar:
Un consejo más: en tu mensaje se ve un token de sesión del servicio. Edita el mensaje y borra esa línea, por si el token sigue siendo válido.
Si me pegas la cabecera Content-Type de la respuesta (solo esa línea) lo concretamos.
Un saludo,
FiveTech AI
elmoiquique wrote: Wed Oct 21, 2026 9:42 pmHola, estoy trabajando con xml y necesito la libreria que contiene el hbtip para xharbour,,, donde la puedo encontrar
Saludos
The correct name is tip.ch.
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Estimado/a elmoiquique,
Gracias. Eso confirma que es MTOM/XOP: la respuesta es multipart/related y el XML con la referencia al PDF va en la primera parte. Ojo: a tu línea le falta el parámetro boundary, que es el que sirve para separar las partes (la cabecera completa suele ser algo como multipart/related; type="application/xop+xml"; boundary="..."; start="..."). Lo que has pegado parece la cabecera de la parte XML, no la de la respuesta HTTP.
Para leer la cabecera de la respuesta HTTP con WinHttp (sin probar):
Code: Select all | Expand
? oHttp:GetResponseHeader( "Content-Type" )
Si nos pegas ese resultado, lo concretamos. Mientras tanto, el método de buscar "%PDF" y el último "%%EOF" en el fichero binario sigue valiendo para sacar el PDF.
Un saludo,
FiveTech AI
multipart/related;boundary="----=_Part_2_1339637348.1792679169970";type="application/xop+xml";start="<soapPart>";start-info="text/xml"
Estimado/a elmoiquique,
Perfecto, ahora sí. El boundary es ----=_Part_2_1339637348.1792679169970 (ojo: cambia en cada respuesta, hay que leerlo siempre de la cabecera). Cada parte empieza con "--" + boundary, y la última con "--" + boundary + "--". El PDF va en la segunda parte, después de su propia cabecera (termina en una línea en blanco, CRLF CRLF) y hasta el CRLF previo al siguiente delimitador.
Ejemplo mío, sin probar (hay que adaptarlo y comprobar que el PDF abre bien). Parte de que ya has guardado la respuesta binaria completa en un fichero (cFile) con ADODB.Stream, como te dije, y de que MemoRead() lee el fichero sin alterar los bytes:
Code: Select all | Expand
FUNCTION ExtraePdf( cFile, cContentType, cPdfOut )
LOCAL cData, cBoundary, cDelim, nIni, nFin, nCab, cPdf, n
// 1) boundary de la cabecera Content-Type de la respuesta
n := At( 'boundary="', cContentType )
IF n == 0
RETURN .F.
ENDIF
cBoundary := SubStr( cContentType, n + 10 )
cBoundary := Left( cBoundary, At( '"', cBoundary ) - 1 )
cDelim := "--" + cBoundary
cData := MemoRead( cFile )
// 2) saltar la primera parte (el XML) y entrar en la segunda
nIni := At( cDelim, cData ) // inicio de la parte 1
nIni := At( cDelim, cData, nIni + 1 ) // inicio de la parte 2 (PDF)
IF nIni == 0
RETURN .F.
ENDIF
// 3) el cuerpo empieza tras la línea en blanco de la cabecera de esa parte
nCab := At( CHR(13) + CHR(10) + CHR(13) + CHR(10), cData, nIni )
IF nCab == 0
RETURN .F.
ENDIF
nCab += 4
// 4) el cuerpo acaba antes del CRLF que precede al siguiente delimitador
nFin := At( CHR(13) + CHR(10) + cDelim, cData, nCab )
IF nFin == 0
RETURN .F.
ENDIF
cPdf := SubStr( cData, nCab, nFin - nCab )
MemoWrit( cPdfOut, cPdf ) // si MemoWrit añade algo, usa FCreate/FWrite
RETURN File( cPdfOut )
El Content-Type lo sacas con oHttp:GetResponseHeader( "Content-Type" ), y como entrada usas la respuesta guardada en binario. Si el PDF sale corrupto, comprueba primero que el fichero guardado tiene el tamaño de la respuesta (oHttp:ResponseBody) y que no se ha convertido a texto por el camino.
Un saludo,
FiveTech AI
este es el programa,,, pero cuando separo el pdf, queda corrupto
FUNCTION RDOCLPT(TS_TOKEN)
LOCAL oHttp,Doc,cxmLbody,oIni,nHandle,ctype,cxml
LOCAL ts_exit:=.t.,tw_servidor:='',ts_mj1:='',ts_modulo:=.f.
LOCAL ts_servidor:="https://sveqa.zofri.cl/sveProcDocWSN/Emision?WSDL"
LOCAL hreturn
if empty(ts_token)
msginfo('Debe Obtener un Token de Inicio para Autentificarse en Web Service','Token de Sesion')
return .f.
endif
cXmlBody:= '' +;
'<?xml version="1.0" encoding="utf-8"?>' + ;
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cl="cl.zofri.sve" xmlns:wsn="http://cl/zofri/sve/prd/wsn">'+;
' <soapenv:Header>'+;
' <cl:token>'+ts_token+'</cl:token>'+;
' </soapenv:Header>'+;
' <soapenv:Body>'+;
' <wsn:emisionDocumento>'+;
' <wsn:codigoAduaneroDoc>201-25-347632</wsn:codigoAduaneroDoc>'+;
' <wsn:tipoEmision>E</wsn:tipoEmision>'+;
' </wsn:emisionDocumento>'+;
' </soapenv:Body>'+;
'</soapenv:Envelope>'
TRY
oHttp := CreateObject( 'MSXML2.XMLHTTP.6.0' )
CATCH
oHttp := CreateObject( 'Microsoft.XMLHTTP' )
END
doc = CreateObject("MSXML2.DOMDocument.6.0")
oHttp:Open( "POST" , ts_servidor, .F. )
oHttp:SetRequestHeader( "Accept-Encoding","gzip,deflate" )
ohttp:SetRequestHeader( "Content-Type" , "application/soap+xml" )
doc:LoadXML( cXmlbody )
TRY
oHttp:Send(DOC:XML)
CATCH
?'ERROR'
RETURN .T.
END
IF oHttp:Status == 200
cXml := oHttp:ResponseBody
cType := oHttp:GetResponseHeader( "Content-Type" )
ENDIF
?CXML
?ctype
hb_memowrit( "file1.txt", ohttp:responseBODY)
hb_memowrit( "file2.txt", ctype)
RETURN .F.
Estimado/a elmoiquique,
Gracias por pegar el programa. No veo en él la parte donde separas el PDF, que es donde suele estar el fallo, así que te doy dos cosas: dónde puede estar el problema y una comprobación que lo delimita. Todo lo que sigue es mío y sin probar.
1) Lo más probable es que los bytes ya se estropeen antes de separar nada. En tu código haces hb_memowrit( "file1.txt", ohttp:responseBODY ). ResponseBody es un array de bytes de COM (un SAFEARRAY), y según cómo lo convierta tu versión de xHarbour a cadena puede cambiar bytes (los que superan el 127, el 0 o los 13/10). En un PDF eso lo corrompe. Para descartarlo, guarda la respuesta con ADODB.Stream, que escribe los bytes tal cual:
Code: Select all | Expand
oStm := CreateObject( "ADODB.Stream" )
oStm:Type := 1 // binario
oStm:Open()
oStm:Write( oHttp:ResponseBody )
oStm:SaveToFile( "file1.bin", 2 ) // 2 = sobrescribir
oStm:Close()
2) Comprueba el tamaño: el fichero file1.bin debe medir lo mismo que la respuesta. Si file1.txt (el tuyo) pesa distinto, ahí está el problema.
3) Si el tamaño coincide y sigue corrupto, el fallo está en el corte. Abre file1.bin con un editor hexadecimal y comprueba: que la parte del PDF empiece justo en "%PDF-" (sin la cabecera de la parte, ni líneas en blanco antes) y que termine en "%%EOF" sin incluir el CRLF ni el delimitador "------=Part..." que viene detrás. Un solo byte de más o de menos al principio o al final suele ser suficiente para que el visor diga que está dañado.
4) Detalle del código: en el POST envías Content-Type "application/soap+xml" (SOAP 1.2), pero la respuesta dice type="application/xop+xml" con start-info="text/xml" (SOAP 1.1). Si el servicio responde bien no pasa nada, pero lo normal para SOAP 1.1 es "text/xml; charset=utf-8" más la cabecera SOAPAction. Es solo una observación, no la causa del PDF dañado.
Si me pegas el trozo de código con el que cortas el PDF, y el tamaño del fichero guardado frente al de la respuesta, lo vemos con más precisión.
Un saludo,
FiveTech AI
gracias, por la ayuda,, todo resuelto....