2010-03-07 14 views
20

Attualmente sto cercando di eseguire lo streaming di contenuti sul Web dopo un processo di codifica. Questo di solito funziona bene scrivendo file binari sul mio web stream, ma alcuni browser (in particolare IE7, IE8) non amano il fatto che il Content-Length non sia definito nell'intestazione HTTP. Credo che le intestazioni "valide" debbano avere questo set.Intestazioni HTTP per contenuto sconosciuto Lunghezza

Qual è il modo corretto per lo streaming di contenuti sul Web quando si dispone di un Content-Length sconosciuto? Il processo di codifica può richiedere un po ', quindi voglio iniziare lo streaming non appena viene completato.

risposta

18

Provare a inviarli in blocchi insieme a Transfer-Encoding:chunked. Maggiori dettagli in wikipedia.

Aggiornamento come per i commenti, ecco un esempio di come un "ChunkedOutputStream" in Java può apparire come:

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

} 

... che può essere utilizzato come sostanzialmente:

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

Vedete nella fonte, ogni pezzo di dati esiste di un'intestazione che rappresenta la lunghezza dei dati in esadecimale, un CRLF, i dati effettivi e un CRLF. La fine del flusso è rappresentata da un'intestazione che indica una lunghezza 0 e due CRLF.

Nota: nonostante l'esempio, che effettivamente fare non bisogno in un webapplication basato JSP/Servlet. Ogni volta che la lunghezza del contenuto non è impostata su una risposta, il webcontainer li trasferirà automaticamente in blocchi.

+0

Ho provato a utilizzare i blocchi e Firefox si bloccava quando li riceveva. Sto trasferendo dati binari, devo convertirlo in esadecimale per usare i pezzi? Ci sono delle librerie .NET disponibili per questo? – jocull

+1

No, non è necessario convertire. E mi aspetto che .NET gestisca questo automaticamente se non specifichi la lunghezza del contenuto in anticipo. –

+0

Fai clic sul collegamento dietro "Chunked" e sul link di Wikipedia per avere un'idea di come dovrebbe essere. Non lo faccio. NET, quindi non posso dare molto, ma posso dare un esempio basato su Java in un esteso 'OutputStream'. Fai sapere se ti piacerebbe vederlo. – BalusC

2

Proprio come follow-up per l'eccellente post di BalusC, ecco il codice che sto usando in C#. Sto tagliando manualmente i dati direttamente su un flusso di output HTTP, dopo aver ricevuto i dati dallo STDOUT su un processo.

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

Buon lavoro, felice che ti abbia aiutato. – BalusC

Problemi correlati