Need to decompress string compressed with zlib. Can I manually add the "customized wrapper" intersystems requires for $System.Util.Decompress()
Hi,
We're getting a string sent to us by a client that was compressed using a java deflater (the zlib algorithm) and when trying to use $System.Util.Decompress() I get an "illegal value" error. I gather from other community posts that this is because the raw compressed string is missing the customized wrapper Iris automatically adds. I know this has been a longstanding issue for a while...just wanted to check if there'd been any updates to this functionality, or successful workarounds for decompressing raw zlib compressed data. Thanks in advance!
Comments
Please check this previous post:
If you still have questions, reply here for more details.
Hi thanks! In the previous post you said "Unfortunately Decompress() needs the custom wrapper, and I don't know how to make it up" which is what I'd be looking to do. I need to decompress raw contents. So is there a way to add that wrapper? Or some other workaround to to accomplish this?
Appreciate the quick reply!
If I understand correctly you need to deflate and I suppose you want to add the custom wrapper to use $System.Util.Decompress(), if so...you can't. I mean you can't use $System.Util.Decompress() BUT, you can indeed deflate using I/O as in the example I posted in that post/thread.
Here is a sample method to deflate without using file I/O and using XDEV instead.
ClassMethod UnDeflate(Compressed As %String, Output UnDeflated As %String) As %Status
{
Set sc=$$$OK
Try {
; open XDEV device
Set dev="|XDEV|"_+$JOB
Open dev:($ZF(-6,$$$XSLTLibrary,12):/HOSTNAME="XSLT") Use dev
; write compressed string
Write Compressed
; flush buffers
Write *-3
; change device mode to deflate and rewind
Use dev:(:/COMPRESS="DEFLATE":/POSITION=0)
; read uncompressed content
Read UnDeflated
} Catch CatchError {
#dim CatchError as %Exception.SystemException
Set sc=CatchError.AsStatus()
}
Close dev
Quit sc
}I really wish that InterSystems implement the various compress/deflate/gzip functionality available in device I/O as utility methods. Without silly wrappers! 馃槈
Another wish, please InterSystems document XDEV device I/O.
Thank you! So we already have the deflated data sent to us from a client in an http header - we need to decompress it only (not compress it). It seems like this is not possible, but I appreciate you confirming! We're looking into pulling in a python library for the decompression.
Agreed it would be nice for intersystems to add this for generic zlib compression/decmopression
The code I posted does exactly what you need.
You can compress/decompress with deflate or gzip using device I/O.
Oh thank you for clarifying! When trying to implement this code we're getting a <WRITE> error at zUnDeflate + 7, the line "Write Compressed" - have you ever experienced that before?
EPTEST>Set comp=$system.Encryption.Base64Decode("y61UKEstqlTIyc9LVyguKcoEUuUZmckZCnmpqSnFCiX5CkmpCimpaTmJJakpAA==")
EPTEST>Set sc=##class(Community.Compress).UnDeflate(comp,.uncomp)
EPTEST>Write uncomp
my very long string which needs to be deflatedWorks fine for me
Thank you for verifying - when we run it from terminal using the string you provided we get an "End of File" error. Maybe this means our systems our configured differently?
Regardless thank you for the quick responses and information!
Just dropping this here because I spent DAYS try to figure out how to get PDF to read a zlib from Intersystems.
You'll see code above to use $e(string,4,*-5) to make it "deflate" but PDF wants ZLIB.
The issue turned out to be that Intersystems adds a first # character and a last character around the zlib compression.
If you do this:
S pdfcompress=$E($System.Util.Compress(instring,"zlib"),2,*-1) ; remove first and last character
THEN the pdf reader properly reads and processes that in the stream object (when using /FlateDecode)
Wasted days just because of 2 added characters. Hope this helps someone else.