未知内容长度的HTTP标头

时间:2010-03-07 04:33:25

标签: .net http binary streaming http-headers

我目前正在尝试在转码过程之后将内容流式传输到网络上。这通常可以通过将二进制文件写入我的Web流来正常工作,但是某些浏览器(特别是IE7,IE8)不喜欢不在HTTP头中定义Content-Length。我相信“有效”标题应该有这个设置。

当您有未知的内容长度时,将内容流式传输到网络的正确方法是什么?转码过程可能需要一段时间,因此我希望在完成时开始流式传输。

2 个答案:

答案 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);