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

82

Esta pergunta já tem uma resposta aqui:

Ocasionalmente, ao fazer o download de um arquivo em um navegador da Web, o progresso do download não "sabe" o tamanho total do arquivo ou a duração do download - apenas mostra a velocidade na qual está sendo baixado, com um total como "Desconhecido".

Por que o navegador não saberia o tamanho final de alguns arquivos? Onde ela obtém essas informações em primeiro lugar?

Coldblackice
fonte
13
Os arquivos criados dinamicamente não têm tamanho, eles aparecem como um fluxo até que o EOF seja atingido.
Fiasco Labs

Respostas:

114

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

Primeiro, seu 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 ( User-Agent etc). Por exemplo, para carregar a página principal no site SuperUser http://superuser.com/, meu navegador envia uma solicitação com a seguinte aparência:

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 ficam assim:

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 não for esse o caso, o código será outra coisa e fornecerá alguma indicação do motivo pelo qual o servidor não está apenas retornando um documento como resposta: por exemplo, se não conseguir encontrar o documento solicitado, ele deverá retornar 404 Not Found, e se você não tiver permissão para acessar o conteúdo em questão, ele deverá 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 o dele Content-type.

Em seguida é uma linha vazia. Isso indica que não haverá mais cabeçalhos de resposta. Tudo além dessa linha é o conteúdo do documento solicitado. Portanto, no exemplo acima, <!DOCTYPE html>é a primeira linha da página inicial do Superusuário (um documento HTML). Se eu estivesse solicitando o download de um documento, provavelmente haveria alguns caracteres sem sentido, porque a maioria dos formatos de documento é ilegível sem processamento prévio.

Voltar 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, portanto, 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 rapidamente), às vezes os programadores preguiçosos não o incluem (bastante comum nos sites de download de drivers), às vezes os sites são criados por iniciantes que não sabem de tal cabeçalho.

De qualquer forma, seja qual for o motivo, o cabeçalho pode estar ausente. Nesse caso, o navegador não sabe quantos dados o servidor 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.

gronostaj
fonte
4
Uma observação muito, muito pequena: os navegadores suportam protocolos diferentes do 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
5
@RobertFisher FTP é um protocolo raro? : p
Thomas
5
@ Thomas Esta é a minha experiência nos dias de hoje. Faz vários anos desde que me lembro de ter visto uma URL ftp no meu navegador. Alguns anos atrás, eu estava usando o ftp - diretamente, e não com um navegador - no trabalho (quase inteiramente carregamentos), mas essas tarefas são tratadas pelo scp agora. A única coisa que uso hoje para o ftp é enviar conteúdo para um host minimalista. Claro, YMMV. ^ _ ^
Robert Fisher
2
Este é exatamente o tipo de resposta que me faz amar este site. Como concedo uma recompensa?
Aquele cara brasileiro
1
@ ruda.almeida de você discorda disso, você pode postar sobre isso em meta.superuser.com, será discutido e talvez alguém reabra a pergunta.
gronostaj
54

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

Ignacio Vazquez-Abrams
fonte
1
Para ser mais 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-Lengthcampo do cabeçalho for usado ou o documento for transferido Transfer-Encoding: chunked. O último permite gerar conteúdo dinamicamente e enviá-lo por partes à medida que é gerado e é capaz de sinalizar o final do documento.
X4u
3

Quando o conteúdo (por exemplo, um .pdfdocumento ou uma planilha do Excel) é criado em tempo real, o tamanho não pode ser conhecido antes. Nesse caso, o servidor não pode enviar o tamanho do download antes e o navegador não pode exibir o tamanho total.

Uwe Plonus
fonte
9
A @alfo terá que discordar ... se estou transmitindo vídeo ou mesmo transmitindo qualquer tipo de dados que não seja de tamanho fixo, se o objetivo é levar os dados ao usuário o mais rápido possível, Eu não vou saber o tamanho no ponto onde eu começo a transmissão
Foon
4
@Alfo Você pode criar dados como .pdfarquivos em tempo real. Contanto que os dados não sejam escritos de forma competitiva, você não sabe o tamanho, mas pode enviar o ata já para o navegador. Eu já fiz isso em Java e enviei um arquivo do Excel para o navegador que, como gerado em tempo real. Do lado dos navegadores, parecia um download, mas do lado dos servidores, é um streaming. Portanto, é possível transmitir .pdf arquivos, mesmo que você não possa imaginar isso. No navegador, parece um download sem tamanho conhecido.
Uwe Plonus
8
@Alfo - ele precisa ser concluído apenas antes que o último pacote seja enviado ao cliente.
precisa
4
@Alfo Eu nunca falei sobre vapor de vídeo, mas sobre o streaming em geral, que também pode estar transmitindo um .pdfarquivo ou uma planilha do Excel!
Uwe Plonus
2
@Alfo - Você tem um ponto válido, os 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 muitos pacotes, faz sentido que o servidor comece a enviar os blocos conforme são calculados (em vez de precisar criar todos os arquivos grandes na memória e depois Envie isto). O HTTP 1.1 projetou especificamente a codificação de transferência em partes para esse fim.
precisa saber é