Vraag HTTP-headers voor onbekende inhoud-lengte


Ik probeer momenteel inhoud naar internet te streamen na een transcoderingsproces. Dit werkt meestal goed door binaire gegevens naar mijn webstream te schrijven, maar sommige browsers (met name IE7, IE8) vinden het niet prettig dat de inhoudslengte niet is gedefinieerd in de HTTP-header. Ik geloof dat "geldige" headers deze set zouden moeten hebben.

Wat is de juiste manier om inhoud naar internet te streamen als je een onbekende lengte hebt? Het transcoderingsproces kan een tijdje duren, dus ik wil het gaan streamen zodra het is voltooid.


21
2018-03-07 04:33


oorsprong


antwoorden:


Probeer ze samen met brokken mee te sturen Transfer-Encoding:  chunked. Meer details in wikipedia.

Bijwerken volgens de reacties, hier is een voorbeeld hoe een "ChunkedOutputStream" in Java er als volgt uit kan zien:

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

}

... die in principe kan worden gebruikt als:

OutputStream output = new ChunkedOutputStream(response.getOutputStream());
output.write(....);

U ziet in de bron dat elk brok gegevens bestaat uit een koptekst die de lengte van gegevens in hexadecimaal, een CRLF, de werkelijke gegevens en een CRLF vertegenwoordigt. Het einde van de stroom wordt weergegeven door een kop die een lengte 0 en twee CRLF's aangeeft.

Notitie: ondanks het voorbeeld doe je dat eigenlijk wel niet nodig hebben in een JSP / Servlet-gebaseerde webapplicatie. Wanneer de lengte van de inhoud niet is ingesteld op een antwoord, zal de webcontainer ze automatisch in chunks overbrengen.


19
2018-03-07 04:48



Net als een vervolg op de uitstekende post van BalusC, hier is de code die ik gebruik in C #. Ik chunking gegevens handmatig rechtstreeks naar een HTTP-uitvoerstroom, nadat ik gegevens van de STDOUT over een proces heb ontvangen.

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

2
2018-03-08 18:01