1

我正在尝试通过 java 套接字发送压缩的 HTML 文件,但浏览器显示一个空的 HTML 文件。

问题是,当我尝试发送未压缩的 HTML 时,一切正常(是的,我确实相应地修改了 HTTP 标头)。

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();
}

基本上,标头包含 HTTP 标头,正文包含 HTML 文件。其余的似乎不言自明。什么可能导致这种行为?

编辑:标题是这样生成的:

    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";
4

2 回答 2

3

问题是在调用方法GZIPOutputStream之前 a 不完整。finish()

当您close()流式传输时会自动调用它。

由于您在此byteStream.toByteArray() 之前打电话,因此您没有获得完整的数据。

此外,您不需要拨打电话flush(),因为这也会在您拨打电话时自动完成close()。并关闭GZIPOutputStream自动关闭底层流(即ByteArrayOutputStream)。

所以,你的代码应该是:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.close();
byteBody = byteStream.toByteArray();
于 2019-05-02T19:59:21.593 回答
-1

一个简单的测试类应该会告诉你问题出在哪里:

import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPOutputStream;

public class GZipTest {

    public final static void main(String[] args) throws Exception {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream gzos = new GZIPOutputStream(baos);

        gzos.write("some data".getBytes());
        System.out.println("baos before gzip flush: " + baos.size());
        gzos.flush();
        System.out.println("baos after gzip flush: " + baos.size());
        gzos.close();
        System.out.println("baos after gzip close: " + baos.size());
    }
}

这导致以下输出:

baos before gzip flush: 10
baos after gzip flush: 10
baos after gzip close: 29

GZIPOutputStream在构建你的身体数据后关闭你的,所以浏览器收到不完整的 GZIP 数据,因此无法解压缩它。

于 2019-05-02T19:18:37.053 回答