如何从java servlet中的chunked响应中发送Http预告片/页脚? [英] How do I send Http trailers/footers in a chunked response from within a java servlet?

查看:160
本文介绍了如何从java servlet中的chunked响应中发送Http预告片/页脚?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上我的回复标题包含

Basically my response headers contain

Transfer-encoding = chunked,

Transfer-encoding=chunked,

Trailer = [some trailer I想发送说法例如SomeTrailer]

Trailer=[some trailer I want to send say e.g "SomeTrailer"]

一旦我把数据写入Servlet输出流,我就写了预告片
SomeTrailer: [value],但httpclient没有正确解析。
httpclient将整个inputstream(包括预告片)视为单个
块。
我已经尝试在将数据写入输出流之后在回复标题中编写预告片但没有成功。

Once I'm done writing the data to the Servlet outputstream, I'm writing the trailer "SomeTrailer:[value]", but this is not being parsed by the httpclient correctly. The httpclient considers the whole of inputstream (including the trailer) as a single chunk. I've also tried writing the trailer in a response header after the data has been written to the outputstream but without success.

请帮助

我没有找到任何有用的资料。

I haven't found any good sources on this.

推荐答案

我最终为此编写了一个简单的单线程网络服务器。原来这很容易。服务器很简单。代码有点粗糙,但主要的想法就在那里。

I ended up writing a simple single threaded webserver for this. Turned out it was quite easy. The server is pretty simple. The code's a bit rough though, but the main idea is there.

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

What it does it sends the filecontents as the first chunk and the checksum of the file as a footer.

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

这篇关于如何从java servlet中的chunked响应中发送Http预告片/页脚?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆