Подтвердить что ты не робот

Заголовки HTTP для неизвестного содержимого

В настоящее время я пытаюсь передать контент в Интернет после процесса транскодирования. Обычно это нормально работает, записывая двоичный файл в мой веб-поток, но некоторые браузеры (в частности, IE7, IE8) не любят не иметь Content-Length, определенные в заголовке HTTP. Я считаю, что "действительные" заголовки должны иметь этот набор.

Каков правильный способ потокового контента в Интернете, когда у вас неизвестный Content-Length? Процесс транскодирования может занять некоторое время, поэтому я хочу начать потоковое воспроизведение по мере его завершения.

4b9b3361

Ответ 1

Попробуйте отправить их в куски вместе с Transfer-Encoding: chunked. Подробнее в wikipedia.

Обновить в соответствии с комментариями, вот пример, как выглядит "ChunkedOutputStream" в Java:

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. Всякий раз, когда длина содержимого не задается в ответе, webcontainer автоматически передает их в куски.

Ответ 2

Как и в случае с замечательным сообщением BalusC, вот код, который я использую на С#. Я передаю данные вручную непосредственно в поток вывода HTTP после получения данных из STDOUT в процессе.

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