Large TIFF data via HTTP web service
Posted: Mon Aug 28, 2023 12:07 pm
I am using version 1.45 of HTTPAPI. I need to retrieve large TIFF files via an HTTP web service. The retrieved XML contains a BASE64 encoded TIFF file. I can retrieve the file fine, but the decoded data no longer has TIFF headers, so it is not a valid TIFF image.
My code uses HTTP_DEBUG, but it never generates a log. I have tried both with and without the 2nd parm.
Because the downloaded files could be over 100MB, I save the retrieved XML to the IFS. That part works fine:
I pass the XML to a handler, which also works fine:
My handler checks the event codes, and correctly retrieves the payload:
x@ is a pointer to the XML payload (meaning, the raw, encoded TIFF data, without any XML wrappers):
// Create a heap space that points to the file
The handler works as expected, and retrieves encoded TIFF data. Here is the beginning of one download:
If I copy the entire value into https://codebeautify.org/base64-to-image-converter, it correctly generates the TIFF image.
Next, I decode the data:
Then I save the decoded data:
My problem is the resulting file is not a valid TIFF file. Since I can paste the payload into a BASE64 converter, I know that my http_req() works, and so does the XML handler. To me, that only leaves a CCSID clash as the cause of my problem. Something is not getting the CCSID that it expects, which corrupts the results. I have tried a ton of CCSID options and variations, but nothing I've tried creates a usable TIFF file.
The retrieved XML has this in the header: encoding="utf-8". Since I am saving an image to the IFS, I need the result to use CCSID 1252. After many hours of testing, I learned that RPG does CCSID conversion automatically, so I may not need to use iconv(). But since RPG's auto-conversion requires a CCSID property on a field, I might still need to use iconv() because I'm using pointers.
I've tried setting the CCSID of the raw work file in /tmp to 1208, which didn't help. I've also tried which didn't help, either.
Here is my iconv() proc (which also doesn't create a usable TIFF file):
What am I missing?
My code uses HTTP_DEBUG, but it never generates a log. I have tried both with and without the 2nd parm.
Code: Select all
http_debug(*on: '/tmp/httpapi_debug.txt' );
Code: Select all
// post the XML, and put the return value
// into a temp file in the IFS
rc = http_req( 'POST'
: URL
: %trim(tmpXMLpath) // File to receive
: *omit // String to receive
: *omit // File to send
: SOAP ); // String to send
Code: Select all
// call our XML Handler proc
xml-sax(e) %handler( ONBHandler: XMLInfo )
%xml( %trim(tmpXMLpath): 'doc=file' );
Code: Select all
// We got the requested XML element, so process it
when xEvent = *XML_CHARS;
Code: Select all
if write(XMLInfo.IFSHandleRaw: x@: x@Length) < 0;
// handle error
endif;
// Close and reopen the file
if close(XMLInfo.IFSHandleRaw) < 0;
endif;
XMLInfo.IFSHandleRaw = Open( XMLInfo.rawPath:
O_TextData + O_ReadOnly );
Code: Select all
CRTHS( Me.StreamHeapId: *loval );
Stream@ = ALCHSS( Me.StreamHeapId: FileStatus.Size );
Me.StreamSize = Read( XMLInfo.IFSHandleRaw:
Stream@: FileStatus.Size );
Code: Select all
SUkqAAgAAAASAP4ABAABAAAAAAAAAAABBAABAAAAwAYAAAEBBAABAAAASAkAAAIBAwABAAAAAQAAAAMB
Next, I decode the data:
Code: Select all
Me.DecLen = base64_decode( Stream@
: Me.StreamSize
: outBuf
: Me.StreamSize );
Code: Select all
// Write decoded value to IFS
if write( XMLInfo.IFSHandle: outBuf: Me.DecLen ) < 0;
// handle error
endif;
Close_Stream( XMLInfo.IFSHandle );
The retrieved XML has this in the header: encoding="utf-8". Since I am saving an image to the IFS, I need the result to use CCSID 1252. After many hours of testing, I learned that RPG does CCSID conversion automatically, so I may not need to use iconv(). But since RPG's auto-conversion requires a CCSID property on a field, I might still need to use iconv() because I'm using pointers.
I've tried setting the CCSID of the raw work file in /tmp to 1208, which didn't help. I've also tried
Code: Select all
HTTP_SetFileCCSID( 1208 );
Here is my iconv() proc (which also doesn't create a usable TIFF file):
Code: Select all
decBuf = RW_iConv( outBuf: Me.DecLen: 1252 );
Code: Select all
//====================================================================
// RW_iConv: convert CCSID's
//====================================================================
P RW_iConv B export
D RW_iConv PI *
D pInputPtr * const
D pInputLen 10i 0 const
D pToCCSID 5 0 const
D local DS likeds(QTQCODE_t) inz( *likeds )
D remote DS likeds(QTQCODE_t) inz( *likeds )
D toLocal DS likeds(iConv_t)
D toRemote DS likeds(iConv_t)
D inpPtr S *
D inpPtrP S *
D inpLen S 10U 0
D inpPtr64 S 64a based( inpPtr )
D outPtr S *
D outLen S 10U 0
D outPtr64 S 64a based( outPtr )
D inLeft S 10U 0
D outLeft S 10U 0
D rc S 10U 0
local.CCSID = *zero; // I've also tried 1208
remote.CCSID = pToCCSID;
outPtr = %alloc( pInputLen );
inpPtr = pInputPtr;
toRemote = *ALLx'00';
toRemote = QtqIconvOpen( remote: local );
if toRemote.return_value = -1;
// handle error
endif;
inLeft = pInputLen;
outLeft = pInputLen;
rc = iconv( toRemote: inpPtr: inLeft: outPtr: outLeft );
if rc = ICONV_FAIL;
// handle error
endif;
iconv_close(toRemote);
return outPtr;
P RW_iConv E
What am I missing?