views:

109

answers:

3

I am trying to GZip content in a variable to output to the browser. To start I am making this very simple and not worrying about browsers that do not support gzip. Also I have put this together from researching several methods that I could find on the web. Some of them from people that may be reading this question.

<cfsavecontent variable="toGZIP"><html><head><title>Test</title></head><body><h1>Fear my test</h1></body></html></cfsavecontent>

<cfscript>
ioOutput = CreateObject("java","java.io.ByteArrayOutputStream");
gzOutput = CreateObject("java","java.util.zip.GZIPOutputStream");

ioOutput.init();
gzOutput.init(ioOutput);

gzOutput.write(toGZIP.getBytes("UTF-8"), 0, Len(toGZIP.getBytes()));

gzOutput.finish();
gzOutput.close();
ioOutput.flush();
ioOutput.close();

toOutput=ioOutput.toString("UTF-8");
</cfscript>

<cfcontent reset="yes" /><cfheader name="Content-Encoding" value="gzip"><cfheader name="Content-Length" value="#ArrayLen( toOuptut.getBytes() )#" ><cfoutput>#toOuptut#</cfoutput><cfabort />

But I get an error in Firefox (and chrome and Safari)

Content Encoding Error

The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.

Anybody have any ideas?

OS: Mac OX-X Snow Leopard
CF: 9-Dev
Webserver: Apache


SOLUTION

<cfsavecontent variable="toGZIP"><html><head><title>Test</title></head><body><h1>Fear my test</h1></body></html></cfsavecontent>

<cfscript>
ioOutput = CreateObject("java","java.io.ByteArrayOutputStream");
gzOutput = CreateObject("java","java.util.zip.GZIPOutputStream");

ioOutput.init();
gzOutput.init(ioOutput);

gzOutput.write(toGZIP.getBytes(), 0, Len(toGZIP.getBytes()));

gzOutput.finish();
gzOutput.close();
ioOutput.flush();
ioOutput.close();

toOutput=ioOutput.toByteArray();
</cfscript>

<cfheader name="Content-Encoding" value="gzip"><cfheader name="Content-Length" value="#ArrayLen(toOutput)#" ><cfcontent reset="yes" variable="#toOutput#" /><cfabort />
+3  A: 

The follow line look completely wrong:

toOutput=ioOutput.toString("UTF-8");

You encode the GZip stream with UTF8. The result are garbage data. The best you set the GZip data as binary if ColdFusion has the option. If you can only set a string then you need an encoding that not change any bytes. For example iso1.

Horcrux7
I'm not sure what you mean. What do you suggest? I think you may be right, but I don't know what else to do.
Tyler Clendenin
Ahha, I figured it out, you are right. I removed the toString and just outputed it as binary, then used the cfcontent tag's variable attribute to send the binary to the browser.
Tyler Clendenin
A: 

Please note that you have syntax error in the code: toOuptut instead of toOutput.

Unfortunately, I'm not a Java expert and can't say what exactly is wrong. But when I try to save the contents into the file using wget, it contains not zipped binary, but source HTML. It can mean that gzOutput-related processing does not produce correct output.

BTW, verifying the browser support of GZip is pretty simple. You can check the Accept-Encoding header, like this:

<cfif FindNoCase("gzip", cgi.HTTP_ACCEPT_ENCODING)>
    <!--- prepare the gzipped text --->
</cfif>
Sergii
Yeah, the toOuptut was a copy paste issue because I was condensing the code into something that would look better here, oops.
Tyler Clendenin
A: 

Is there a reason you're doing it manually over letting the web server (IIS or Apache) handle this? Both of them support GZip encoding, and will probably do so faster and better than your manual process.

Adam Tuttle
I was going to be doing my own caching in gzip since IIS does not cache dynamically generated content. I was going to have IIS just gzip the static cachable content.
Tyler Clendenin