我目前正在尝试在转码过程之后将内容流式传输到网络上。这通常可以通过将二进制文件写入我的Web流来正常工作,但是某些浏览器(特别是IE7,IE8)不喜欢不在HTTP头中定义Content-Length。我相信“有效”标题应该有这个设置。
当您有未知的内容长度时,将内容流式传输到网络的正确方法是什么?转码过程可能需要一段时间,因此我希望在完成时开始流式传输。
答案 0 :(得分:19)
尝试与Transfer-Encoding:
chunked
一起发送。 wikipedia中的更多详细信息。
更新,以下是Java中“ChunkedOutputStream”的示例:
package com.stackoverflow.q2395192;
import java.io.IOException;
import java.io.OutputStream;
public class ChunkedOutputStream extends OutputStream {
private static final byte[] CRLF = "\r\n".getBytes();
private OutputStream output = null;
public ChunkedOutputStream(OutputStream output) {
this.output = output;
}
@Override
public void write(int i) throws IOException {
write(new byte[] { (byte) i }, 0, 1);
}
@Override
public void write(byte[] b, int offset, int length) throws IOException {
writeHeader(length);
output.write(CRLF, 0, CRLF.length);
output.write(b, offset, length);
output.write(CRLF, 0, CRLF.length);
}
@Override
public void flush() throws IOException {
output.flush();
}
@Override
public void close() throws IOException {
writeHeader(0);
output.write(CRLF, 0, CRLF.length);
output.write(CRLF, 0, CRLF.length);
output.close();
}
private void writeHeader(int length) throws IOException {
byte[] header = Integer.toHexString(length).getBytes();
output.write(header, 0, header.length);
}
}
...基本上可以用作:
OutputStream output = new ChunkedOutputStream(response.getOutputStream());
output.write(....);
在源代码中,每个数据块都存在一个标题,表示以十六进制表示的数据长度,CRLF,实际数据和CRLF。流的末尾由表示0长度和两个CRLF的标题表示。
注意:尽管有这样的示例,但实际上您在基于JSP / Servlet的Web应用程序中不需要它。每当响应中没有设置内容长度时,webcontainer将自动以块的形式传输它们。
答案 1 :(得分:2)
作为BalusC优秀帖子的后续内容,以下是我在C#中使用的代码。在从进程上的STDOUT接收数据后,我手动将数据直接手动分组到HTTP输出流。
int buffSize = 16384;
byte[] buffer = new byte[buffSize];
byte[] hexBuff;
byte[] CRLF = Encoding.UTF8.GetBytes("\r\n");
br = new BinaryReader(transcoder.StandardOutput.BaseStream);
//Begin chunking...
int ret = 0;
while (!transcoder.HasExited && (ret = br.Read(buffer, 0, buffSize)) > 0)
{
//Write hex length...
hexBuff = Encoding.UTF8.GetBytes(ret.ToString("X"));
e.Context.Stream.Write(hexBuff, 0, hexBuff.Length);
//Write CRLF...
e.Context.Stream.Write(CRLF, 0, CRLF.Length);
//Write byte content...
e.Context.Stream.Write(buffer, 0, ret);
//Write CRLF...
e.Context.Stream.Write(CRLF, 0, CRLF.Length);
}
//End chunking...
//Write hex length...
hexBuff = Encoding.UTF8.GetBytes(0.ToString("X"));
e.Context.Stream.Write(hexBuff, 0, hexBuff.Length);