2010-03-10 17 views
27

Sto provando a valutare i pro e i contro dell'impostazione dell'intestazione HTTP Content-Length rispetto alla codifica Chunked per restituire [probabilmente] file di grandi dimensioni dal mio server. Uno o l'altro è necessario per essere compatibile con le specifiche HTTP 1.1 usando connessioni persistenti. Vedo il vantaggio dell'essere Content-Length intestazione:Codifica Content-Length contro codifica Chunked

  • Scarica le finestre di dialogo possono mostrare barra di precisione di avanzamento
  • Il cliente sa in anticipo se il file può/non può essere troppo grande per loro di ingerire

Il il rovescio della medaglia è dover calcolare la dimensione prima di restituire l'oggetto che non è sempre pratico e potrebbe aggiungere all'utilizzo del server/database. Lo svantaggio della codifica Chunked è il piccolo sovraccarico di aggiungere la dimensione del blocco prima di ogni blocco e la barra di avanzamento del download. qualche idea? Qualche altra considerazione HTTP per entrambi i metodi a cui potrei non aver pensato?

+1

E 'un dato che il contenuto è statico e la sua lunghezza è noto a priori? In caso contrario, Chunked sarebbe molto più veloce per file di grandi dimensioni. –

risposta

27

Utilizzare Content-Length, sicuramente. L'utilizzo del server da questo sarà quasi inesistente e il vantaggio per gli utenti sarà grande.

Per il contenuto dinamico, è anche abbastanza semplice aggiungere il supporto di risposta compressa (gzip). Ciò richiede il buffering dell'output, che a sua volta fornisce la lunghezza del contenuto. (non pratico con download di file o contenuto già compresso (audio, immagini)).

Prendere in considerazione anche l'aggiunta del supporto per il contenuto parziale /byte-range, ovvero la possibilità di riavviare i download. See here for a byte-range example (l'esempio è in PHP, ma è applicabile in qualsiasi lingua). Hai bisogno di Content-Length quando servi contenuti parziali.

Ovviamente, quelli non sono puntini d'argento: per i media di streaming, è inutile utilizzare il buffering dell'output o la dimensione della risposta; per i file di grandi dimensioni, il buffering dell'output non ha senso, ma Content-Length e byte serving hanno molto senso (è possibile riavviare un download non riuscito).

Personalmente, servo Content-Length ogni volta che lo so; per il download di file, controllare la dimensione del file è insignificante in termini di risorse. Risultato: l'utente ha una determinata barra di avanzamento (e le pagine dinamiche si scaricano più velocemente grazie a gzip).

+1

Non vedo come la gamma di byte che serve (in pratica: "resume downloads") sia utile in questo caso particolare. Ciò richiede che la lunghezza del contenuto sia nota in anticipo. È quindi possibile impostare correttamente la lunghezza del contenuto. – BalusC

+0

@BalusC: Content-Length è un ** prerequisito ** per la pubblicazione di byte. Caso di utilizzo tipico: l'utente sta scaricando un file da 10 MB tramite la sua connessione WiFi, il segnale scende di 7 MB nel download. Senza riprendere, deve scaricare di nuovo l'intero 10 MB, il che è abbastanza fastidioso per lei; con curriculum, rimangono solo 3 MB. La maggior parte dei browser moderni supporta questo. – Piskvor

+0

Sì, lo so. Forse non mi hai capito? Sto solo dicendo che non vedo come questo sia correlato alla "lunghezza del contenuto" v.s. "trasferimento-codifica: chunked" domanda. A proposito, la cronologia dei post dell'OP mi dice che la sua lingua principale è Java, in questo caso l'esempio di 'FileServlet' potrebbe essere più utile: http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume- e.html – BalusC

10

Se la lunghezza del contenuto è nota in anticipo, sicuramente la preferirei sopra all'invio in blocchi. Se ci sono mezzi di file statici sul file system del disco locale o in un database, allora qualsiasi linguaggio di programmazione rispettato e RDBMS fornisce modi per ottenere in anticipo la lunghezza del contenuto. Dovresti farne uso.

D'altra parte, se la lunghezza del contenuto è davvero imprevedibile in precedenza (ad esempio quando l'intento è comprimere più file insieme e inviarlo come uno), quindi l'invio in blocchi può essere più veloce del buffering nella memoria del server o prima scrivere sul file system del disco locale. Ma questo influisce negativamente sull'esperienza utente perché il progresso del download è sconosciuto. L'impaziente può quindi interrompere il download e andare avanti.

Un altro vantaggio di conoscere la lunghezza del contenuto è la possibilità di riprendere i download. Vedo nella tua cronologia che il tuo linguaggio di programmazione principale è Java; potete trovare here un articolo con ulteriori informazioni tecniche di base e un esempio di servlet Java che lo fa.

0

Content-Length

L'intestazione Content-Length determina la lunghezza in byte del corpo della richiesta/risposta. Se trascuri di specificare l'intestazione Content-Length, i server HTTP aggiungeranno implicitamente un'intestazione Transfer-Encoding: chunked. L'intestazione Content-Length e Transfer-Encoding non deve essere utilizzata insieme. Il ricevitore non ha idea di quale sia la lunghezza del corpo e non può stimare il tempo di completamento del download. Se si aggiunge un'intestazione Content-Length, assicurarsi che corrisponda all'intero corpo in byte, se non è corretto, il comportamento dei destinatari non è definito.

L'intestazione Content-Length non consente lo streaming, ma è utile per file binari di grandi dimensioni, in cui si desidera supportare la pubblicazione di contenuti parziali. Ciò significa fondamentalmente download ripristinabili, download in pausa, download parziali e download multi-homed. Ciò richiede l'uso di un'intestazione aggiuntiva denominata Range. Questa tecnica è chiamata Byte serving.

Transfer-Encoding

L'uso di Transfer-Encoding: chunked è ciò che permette lo streaming all'interno di una singola richiesta o risposta. Ciò significa che i dati vengono trasmessi in modo frammentato e non influiscono sulla rappresentazione del contenuto.

Ufficialmente un client HTTP ha lo scopo di inviare una richiesta con un campo di intestazione TE che specifica quali tipi di codifiche di trasferimento il client è disposto ad accettare. Questo non viene sempre inviato, tuttavia la maggior parte dei server suppone che i client possano elaborare le codifiche chunked.

La codifica del trasferimento chunked fa un uso migliore delle connessioni TCP permanenti, che HTTP 1.1 assume come valore predefinito.

Content-Encoding

È anche possibile comprimere i dati Chunked o non-chunked. Questo è praticamente fatto tramite l'intestazione Content-Encoding.

Si noti che il Content-Length è uguale alla lunghezza del corpo dopo il Content-Encoding. Ciò significa che se hai gzipato la tua risposta, il calcolo della lunghezza avviene dopo la compressione. Sarà necessario essere in grado di caricare l'intero corpo in memoria se si desidera calcolare la lunghezza (a meno che non si disponga di tali informazioni altrove).

Durante lo streaming utilizzando la codifica Chunked, l'algoritmo di compressione deve supportare anche l'elaborazione in linea. Per fortuna, gzip supporta la compressione del flusso. Credo che il contenuto venga prima compresso e poi tagliato a pezzi. In questo modo, i blocchi vengono ricevuti, quindi decompressi per acquisire il contenuto reale. Se fosse il contrario, otterrai lo stream compresso, e quindi la decompressione ci darebbe dei pezzi. Il che non ha senso.

Una tipica risposta flusso compresso può avere queste intestazioni:

Content-Type: text/html 
Content-Encoding: gzip 
Transfer-Encoding: chunked 

semanticamente l'utilizzo di Content-Encoding indica una "end to end" schema di codifica, il che significa che solo il cliente finale o il server finale si suppone per decodificare il soddisfare. I proxy nel mezzo non sono autorizzati a decodificare il contenuto.

Se si desidera consentire ai proxy nel mezzo di decodificare il contenuto, l'intestazione corretta da utilizzare è infatti l'intestazione Transfer-Encoding. Se la richiesta HTTP possedeva un'intestazione TE: gzip chunked, è legale rispondere con Transfer-Encoding: gzip chunked.

Tuttavia, questo è molto raramente supportato. Quindi dovresti usare solo Content-Encoding per la compressione adesso.

Chunked vs Store & Forward

Problemi correlati