Pergunta

Eu estou tentando pesar os prós e contras de definir o Content-Length HTTP cabeçalho em vez de utilizar a codificação em partes para retornar [possivelmente] arquivos grandes do meu servidor. Um ou o outro é necessário ser compatível com especificações de HTTP 1.1 utilizando ligações persistentes. Eu vejo a vantagem do ser cabeçalho Content-Length:

  • Fazer download diálogos podem mostrar barra de progresso precisa
  • Cliente sabe antecipadamente se o arquivo pode / não pode ser muito grande para eles ingerem

A desvantagem é ter que calcular o tamanho antes de devolver o objeto que nem sempre é prático e poderia adicionar a utilização do servidor / banco de dados. A desvantagem de codificação fragmentada é a pequena sobrecarga de adicionar o tamanho do bloco antes de cada pedaço e a barra de progresso da transferência. Alguma ideia? Quaisquer outras considerações HTTP para ambos os métodos que eu não tenha pensado?

Foi útil?

Solução

Use Content-Length, definitivamente. A utilização do servidor a partir deste será quase inexistente eo benefício para os usuários será grande.

Para conteúdo dinâmico, é também bastante simples para adicionar suporte resposta comprimido ( gzip ). Que requer o buffer de saída, que por sua vez dá-lhe o tamanho do conteúdo. (Não é prático com downloads de arquivos ou conteúdo já comprimido (som, imagens)).

Considere também adicionando suporte para conteúdo parcial / byte-range servir - isto é, capacidade de reiniciar downloads. Ver aqui para um exemplo de intervalo de bytes (o exemplo é em PHP, mas é aplicável em qualquer idioma). Você precisa Content-Length quando servir conteúdo parcial.

É claro que essas não são balas de prata: para streaming media, é inútil para o buffer de saída uso ou tamanho de resposta; para arquivos grandes, o buffer de saída não faz sentido, mas Content-Length e servindo byte faz muito sentido (reiniciar um download não é possível).

Pessoalmente, eu sirvo Content-Length sempre que eu o sei; para download de arquivos, verificar o tamanho do arquivo é insignificante em termos de recursos. Resultado:. Usuário tem uma barra de progresso determinada (e páginas dinâmicas download mais rápido graças à gzip)

Outras dicas

Se o comprimento de conteúdo é conhecido de antemão, então eu certamente preferem-lo acima de envio em pedaços. Se há meio de arquivos estáticos no sistema de arquivos do disco local ou em um banco de dados, então qualquer linguagem de programação auto-respeitado e RDBMS fornece maneiras de obter o tamanho do conteúdo de antemão. Você deve fazer uso dele.

Por outro lado, se o comprimento de conteúdo é realmente imprevisível antemão (por exemplo, quando sua intenção é fechar vários arquivos em conjunto e enviá-lo como um), em seguida, enviá-lo em pedaços pode ser mais rápido do que o buffer na memória ou a escrita de servidor para o sistema de arquivo de disco local primeiro. Mas esse fato afeta a experiência do usuário de forma negativa, porque o progresso do download é desconhecida. A impaciência pode então interromper o download e seguir em frente.

Outra vantagem de saber o tamanho do conteúdo de antemão é a capacidade de retomar downloads. Eu vejo em sua história pós que a sua principal linguagem de programação é Java; pode encontrar aqui um artigo com mais informações técnicas fundo e um exemplo de Java Servlet que faz isso.

Content-Length

O cabeçalho Content-Length determina o comprimento do byte do corpo do pedido / resposta. Se você negligenciar a especificar o cabeçalho Content-Length, servidores HTTP irá adicionar implicitamente um cabeçalho Transfer-Encoding: chunked. O cabeçalho Content-Length e Transfer-Encoding não devem ser usados ??em conjunto. O receptor não terá idéia do que o comprimento do corpo é e não é possível estimar o tempo de download de conclusão. Se você adicionar um cabeçalho Content-Length, verifique se corresponde o corpo inteiro em bytes, se ele estiver incorreto, o comportamento dos receptores é indefinido.

O cabeçalho Content-Length não vai permitir a transmissão, mas é útil para grandes arquivos binários, onde pretende apoiar conteúdo parcial de servir. Isto significa basicamente descargas retomáveis, interromperam carregamentos, descargas parciais, e transferências de multi-hospedada. Isso requer o uso de um cabeçalho adicional chamado Range. Esta técnica é chamada Byte servindo .

Transfer-Encoding

O uso de Transfer-Encoding: chunked é o que permite streaming de dentro de um único pedido ou resposta. Isto significa que os dados são transmitidos de forma fragmentada, e não afetam a representação do conteúdo.

Officially um cliente HTTP é utilizado para enviar uma solicitação com um campo de cabeçalho TE que especifica que tipos de codificações de transferência o cliente está disposto a aceitar. Isto não é sempre enviada, no entanto a maioria dos servidores assumem que os clientes podem processar codificações chunked.

A codificação de transferência chunked faz melhor uso de conexões TCP persistentes, que HTTP 1.1 assume para ser verdade por padrão.

Content-Encoding

Também é possível comprimir fragmentada ou dados não-fragmentada. Isto é praticamente feito via o cabeçalho Content-Encoding.

Note que o Content-Length é igual ao comprimento do corpo após a Content-Encoding. Isto significa que se você tiver compactado sua resposta, então o cálculo do comprimento acontece após a compressão. Você terá que ser capaz de carregar o corpo inteiro na memória, se você quiser calcular o comprimento (a menos que você tem essa informação em outro lugar).

Ao transmitir usando a codificação fragmentada, o algoritmo de compressão deve também suportar o processamento online. Felizmente, suportes gzip transmitir compressão. Eu acredito que o conteúdo é comprimido em primeiro lugar, e em seguida, corte em pedaços. Dessa forma, os pedaços são recebidos, em seguida, descomprimido para adquirir o conteúdo real. Se fosse o contrário, você vai ter o fluxo comprimido, e depois descomprimir nos daria pedaços. Que não faz sentido.

Uma resposta típica corrente de comprimido pode ter estes cabeçalhos:

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

Semanticamente o uso de Content-Encoding indica uma "ponta a ponta" esquema de codificação, o que significa apenas o cliente final ou servidor final é suposto para decodificar o conteúdo. Proxies no meio não são supor para decodificar o conteúdo.

Se você quiser permitir que proxies no meio para decodificar o conteúdo, o cabeçalho correto para uso é de fato o cabeçalho Transfer-Encoding. Se a solicitação HTTP possuía um cabeçalho TE: gzip chunked, então é legal para responder com Transfer-Encoding: gzip chunked.

No entanto, este é muito raramente suportado. Então você só deve usar Content-Encoding para sua compressão no momento.

Chunked vs Store & Atacante

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top