I'm trying to send a compressed HTML file through a java socket but the browser displays an empty HTML file.
The thing is, when I try to send the uncompressed HTML everything works find (yes I do modify the HTTP headers accordingly).
private void sendResponse(String headers, String body) throws IOException
{
BufferedOutputStream output = new BufferedOutputStream(
this.SOCKET.getOutputStream());
byte[] byteBody = null;
// GZIP compression
if(body != null && this.encoding.contains("gzip"))
{
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.flush();
byteBody = byteStream.toByteArray();
byteStream.flush();
byteStream.close();
zipStream.close();
}
else
byteBody = body.getBytes(this.charset);
// Sending response
byte[] msg1 = (Integer.toHexString(byteBody.length) + "\r\n")
.getBytes(this.charset);
byte[] msg2 = byteBody;
byte[] msg3 = ("\r\n" + "0").getBytes(this.charset);
output.write(headers.getBytes(this.charset));
output.write(msg1);
output.write(msg2);
output.write(msg3);
output.flush();
output.close();
}
Basically, headers contains the HTTP headers, and body the HTML file. The rest seems self explanatory. What could cause such a behavior?
EDIT: The header is generated as such:
headers = "HTTP/1.1 200 OK\r\n";
headers += "Date: " + WebServer.getServerTime(Calendar.getInstance()) + "\r\n";
headers += "Content-Type: text/html; charset=" + this.charset + "\r\n";
headers += "Set-Cookie: sessionID=" + newCookie + "; Max-Age=600\r\n";
headers += "Connection: close \r\n";
if(this.encoding.contains("gzip"))
headers += "Content-Encoding: gzip\r\n";
headers += "Transfer-Encoding: chunked \r\n";
headers += "\r\n";
The problem is that a GZIPOutputStream
isn't complete until the finish()
method has been called.
It is automatically called when you close()
the stream.
Since you are calling byteStream.toByteArray()
before that has happened, you're not getting complete data.
Also, you don't need to call flush()
since that is also automatically done when you call close()
. And closing the GZIPOutputStream
automatically closes the underlying stream(s) (i.e. the ByteArrayOutputStream
).
So, you code should be:
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.close();
byteBody = byteStream.toByteArray();