如何从java servlet中的chunked响应中发送Http预告片/页脚?

基本上我的响应头包含

编码传输分块=,

预告片= [我要发送的一些预告片说例如“SomeTrailer”]

一旦我完成了将数据写入Servlet输出流,我正在编写预告片“SomeTrailer:[value]”,但这并没有被httpclient正确解析。 httpclient将整个输入流(包括预告片)视为单个块。 我已经尝试在将数据写入输出流后在响应头中编写预告片,但没有成功。

请帮忙

我没有找到任何好的消息来源。

我最终为此编写了一个简单的单线程Web服务器。 原来这很容易。 服务器很简单。 虽然代码有点粗糙,但主要的想法是存在的。

它的作用是将filecontents作为第一个块发送,并将文件的校验和作为页脚发送。

 import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; public class ChunkedResponseServer implements Runnable { private static final Logger LOGGER = Logger.getLogger(ChunkedResponseServer.class); // Space ' ' static final byte SP = 32; // Tab ' ' static final byte HT = 9; // Carriage return static final byte CR = 13; // Line feed character static final byte LF = 10; final int port; private volatile boolean cancelled = false; public ChunkedResponseServer(int port) { LOGGER.info("Chunked response server running on port " + port); this.port = port; } @Override public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); while (!cancelled) { final Socket connectionSocket = serverSocket.accept(); handle(connectionSocket); } } catch (final IOException e) { throw new RuntimeException(e); } } public void cancel() { LOGGER.info("Shutting down Chunked response Server"); cancelled = true; } private void handle(Socket socket) throws IOException { BufferedReader input = null; DataOutputStream output = null; try { input = new BufferedReader(new InputStreamReader(socket.getInputStream())); output = new DataOutputStream(socket.getOutputStream()); addHeaders(output); addCRLR(output); final String filename = readFilename(input); final byte[] content = readContent(filename); addContentAsChunk(output, content); final String checksum = DigestUtils.md5Hex(content); addLastChunkAndChecksumFooter(output, checksum); addCRLR(output); } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } } private void addLastChunkAndChecksumFooter(DataOutputStream output, String checksum) throws IOException { output.writeBytes("0"); addCRLR(output); output.writeBytes("checksum: " + checksum); addCRLR(output); } private void addContentAsChunk(DataOutputStream output, byte[] content) throws IOException { output.writeBytes(Integer.toHexString(content.length)); addCRLR(output); output.write(content); addCRLR(output); } private void addCRLR(DataOutputStream output) throws IOException { output.writeByte(CR); output.writeByte(LF); } private void addHeaders(DataOutputStream output) throws IOException { output.writeBytes("HTTP/1.1 200 OK"); addCRLR(output); output.writeBytes("Content-type: text/plain"); addCRLR(output); output.writeBytes("Transfer-encoding: chunked"); addCRLR(output); output.writeBytes("Trailer: checksum"); addCRLR(output); } private String readFilename(BufferedReader input) throws IOException { final String initialLine = input.readLine(); final String filePath = initialLine.split(" ")[1]; final String[] components = filePath.split("/"); return components[components.length - 1]; } private byte[] readContent(String filename) throws IOException { final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename); return IOUtils.toByteArray(in); } }