Questão Por que alguns arquivos de download não conhecem seu próprio tamanho? [duplicado]


Esta questão já tem uma resposta aqui:

Ocasionalmente, ao baixar um arquivo em um navegador da Web, o progresso do download não "conhece" o tamanho total do arquivo ou a distância do download - ele mostra apenas a velocidade de download, total como "Desconhecido".

Por que o navegador não sabe o tamanho final de alguns arquivos? De onde vem essa informação em primeiro lugar?


79


origem


Os arquivos criados dinamicamente não têm tamanho, eles aparecem como um fluxo até que o EOF seja atingido. - Fiasco Labs
Duplicação possível de Como o navegador sabe quanto a página foi carregada?, Tempo estimado restante e tamanho total do arquivo não exibido em Download ... - Karan


Respostas:


Para solicitar documentos de servidores da Web, os navegadores usam o protocolo HTTP. Você pode saber esse nome na sua barra de endereços (pode estar oculto agora, mas quando você clica na barra de endereços, copia o URL e cola em algum editor de texto, você verá http:// no inicio). HTTP é um protocolo simples baseado em texto. Funciona assim:

Primeiro, o navegador se conecta ao servidor do site e envia uma URL do documento que deseja baixar (as páginas da Web também são documentos) e alguns detalhes sobre o próprio navegador (Agente de usuário etc). Por exemplo, para carregar a página principal no site do SuperUser, http://superuser.com/, meu navegador envia uma solicitação semelhante a esta:

GET / HTTP/1.1
Host: superuser.com
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.0 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: [removed for security]
DNT: 1
If-Modified-Since: Tue, 09 Jul 2013 07:14:17 GMT

A primeira linha especifica qual documento o servidor deve retornar. As outras linhas são chamadas de cabeçalhos; eles se parecem com isso:

Header name: Header value

Essas linhas enviam informações adicionais que ajudam o servidor a decidir o que fazer.

Se tudo estiver bem, o servidor responderá enviando o documento solicitado. A resposta começa com uma mensagem de status, seguida por alguns cabeçalhos (com detalhes sobre o documento) e, finalmente, se tudo estiver bem, o conteúdo do documento. É assim que a resposta do servidor SuperUser para minha solicitação se parece:

HTTP/1.1 200 OK
Cache-Control: public, max-age=60
Content-Type: text/html; charset=utf-8
Expires: Tue, 09 Jul 2013 07:27:20 GMT
Last-Modified: Tue, 09 Jul 2013 07:26:20 GMT
Vary: *
X-Frame-Options: SAMEORIGIN
Date: Tue, 09 Jul 2013 07:26:19 GMT
Content-Length: 139672

<!DOCTYPE html>
<html>
    [...snip...]
</html>

Após a última linha, o servidor do SuperUser fecha a conexão.

A primeira linha (HTTP/1.1 200 OK) contém o Código de resposta, neste caso é 200 OK. Isso significa que o servidor decidiu que pode retornar um documento, conforme solicitado, e promete que o conteúdo a seguir será esse documento. Se este não for o caso, o código será outra coisa, e fornecerá alguma indicação da razão pela qual o servidor não está apenas retornando um documento como a resposta: por exemplo, se não puder encontrar o documento solicitado, ele deve retornar 404 Not Found, e se você não tem permissão para acessar o conteúdo em questão, ele deve retornar 403 Forbidden.

Após essa primeira linha de status, os cabeçalhos de resposta seguem; eles fornecem mais informações sobre o conteúdo que está sendo retornado, como Content-type.

Em seguida é uma linha vazia. Isso sinaliza o fato de que não haverá mais cabeçalhos de resposta. Tudo depois dessa linha é o conteúdo do documento solicitado. Então, no exemplo acima, <!DOCTYPE html> é a primeira linha da home page do SuperUser (um documento HTML). Se eu estivesse solicitando um documento para download, provavelmente seriam alguns caracteres sem sentido, porque a maioria dos formatos de documentos é ilegível sem processamento prévio.

De volta aos cabeçalhos. O mais interessante para nós é o último, Content-Length. Ele informa ao navegador quantos bytes de dados ele deve esperar após a linha vazia, então basicamente é o tamanho do documento expresso em bytes. Este cabeçalho não é obrigatório e pode ser omitido pelo servidor. Às vezes, o tamanho do documento não pode ser previsto (por exemplo, quando o documento é gerado em tempo real), às vezes os programadores preguiçosos não o incluem (muito comum em sites de download de drivers), às vezes sites são criados por novatos que não sabem de tal cabeçalho.

De qualquer forma, seja qual for o motivo, o cabeçalho pode estar faltando. Nesse caso, o navegador não sabe quantos dados o servidor vai enviar e, portanto, exibe o tamanho do documento como desconhecido, aguardando o servidor fechar a conexão. E essa é a razão para tamanhos de documentos desconhecidos.


108



Uma nota muito, muito pequena: Os navegadores suportam protocolos diferentes de HTTP. Mas outros protocolos são raros hoje em dia, e essencialmente os mesmos conceitos se aplicam a outros protocolos, embora os detalhes sejam diferentes. - Robert Fisher
@RobertFisher FTP é um protocolo raro? : p - Thomas
@ Thomas Essa é a minha experiência nos dias de hoje. Já faz vários anos desde que me lembro de ver um URL de FTP no meu navegador. Há alguns anos, eu estava usando ftp - diretamente, em vez de com um navegador - no trabalho (quase totalmente carrega), mas essas tarefas são tratadas pelo scp agora. A única coisa que eu uso ftp para hoje é o upload de conteúdo para um host da web minimalista. Claro, YMMV. ^ _ ^ - Robert Fisher
Este é exatamente o tipo de resposta que me faz amar este site. Como eu concedo uma recompensa? - That Brazilian Guy
@ ruda.almeida de você não concordar com isso, você pode postar sobre isso em meta.superuser.com, ele será discutido e talvez alguém reabrirá a questão. - gronostaj


O HTTP Content-Length o cabeçalho é opcional em alguns casos e, como tal, pode não ser transmitido com o arquivo; o final do arquivo será sinalizado quando o soquete estiver fechado.


52



Para ser preciso, o HTTP 1.0 definiu o tamanho do conteúdo, fechando o soquete após cada documento. Isso ainda é suportado no HTTP 1.1 para compatibilidade. Mas o HTTP 1.1 permite reutilizar conexões para vários documentos se o Content-Length campo de cabeçalho é usado ou o documento é transferido com Transfer-Encoding: chunked. O último permite gerar dinamicamente conteúdo e enviá-lo por partes à medida que é gerado e é capaz de sinalizar o final do documento. - x4u


Quando o conteúdo (por exemplo, um .pdf documento ou uma folha do Excel) é criado em tempo real, o tamanho não pode ser conhecido antes. Nesses casos, o servidor não pode enviar o tamanho do download antes e o navegador não pode exibir o tamanho total.


2



@alfo terá que discordar ... se eu estiver transmitindo vídeo, ou mesmo se eu estiver transmitindo qualquer tipo de dado que não seja um tamanho fixo, se o objetivo é obter os dados para o usuário o mais rápido possível, Não vou saber o tamanho no ponto em que começo a transmissão - Foon
@Alfo Você pode criar dados como .pdf arquivos na mosca. Contanto que os dados não sejam compilados de forma competente, você não sabe o tamanho, mas você pode enviar as informações já para o navegador. Eu já fiz isso em Java e enviei um arquivo do Excel para o navegador que, como gerado na hora. Do lado dos navegadores, parecia um download, mas do lado dos servidores é um streaming. Então é possível corrente  .pdf arquivos, mesmo que você não possa imaginar isso. Do navegador, parece um download sem comprimento conhecido. - Uwe Plonus
@Alfo - só precisa ser terminado sendo criado antes do último pacote ser enviado para o cliente. - GalacticCowboy
@Alfo eu nunca tomei sobre vídeo fumegante, mas sobre transmissão em geral, que também pode ser streaming de um .pdf arquivo ou uma planilha do Excel! - Uwe Plonus
@Alfo - Você tem um ponto válido, arquivos dinâmicos podem ser inteiramente criados primeiro na memória e depois enviados via HTTP e é fácil calcular o tamanho do conteúdo. No entanto, se o servidor estiver enviando muitos arquivos grandes criados dinamicamente que serão divididos em vários pacotes, faz sentido que o servidor apenas comece a enviar os fragmentos à medida que são calculados (em vez de precisar criar todos os arquivos grandes na memória e depois Envie isto). HTTP 1.1 projetou especificamente o codificação de transferência em partes para este fim. - dr jimbob