¿Por qué algunos archivos de descarga no conocen su propio tamaño? [duplicar]


82

Esta pregunta ya tiene una respuesta aquí:

Ocasionalmente, al descargar un archivo en un navegador web, el progreso de la descarga no "sabe" el tamaño total del archivo, o qué tan avanzado está en la descarga, solo muestra la velocidad a la que se está descargando, con un total como "Desconocido".

¿Por qué el navegador no sabe el tamaño final de algunos archivos? ¿Dónde obtiene esta información en primer lugar?


13
Los archivos creados dinámicamente no tienen un tamaño, se presentan como una secuencia hasta que se alcanza EOF.
Fiasco Labs

Respuestas:


114

Para solicitar documentos de servidores web, los navegadores utilizan el protocolo HTTP. Es posible que conozca ese nombre de su barra de direcciones (puede estar oculto ahora, pero cuando haga clic en la barra de direcciones, copie la URL y péguela en algún editor de texto, verá http://al principio). HTTP es un protocolo simple basado en texto. Funciona así:

Primero, su navegador se conecta al servidor del sitio web y envía una URL del documento que desea descargar (las páginas web también son documentos) y algunos detalles sobre el navegador en sí ( User-Agent, etc.). Por ejemplo, para cargar la página principal en el sitio SuperUser http://superuser.com/, mi navegador envía una solicitud similar 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

La primera línea especifica qué documento debe devolver el servidor. Las otras líneas se llaman encabezados; se ven así:

Header name: Header value

Estas líneas envían información adicional que ayuda al servidor a decidir qué hacer.

Si todo está bien, el servidor responderá enviando el documento solicitado. La respuesta comienza con un mensaje de estado, seguido de algunos encabezados (con detalles sobre el documento) y finalmente, si todo está bien, el contenido del documento. Así es como se ve la respuesta del servidor SuperUser para mi solicitud:

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>

Después de la última línea, el servidor de SuperUser cierra la conexión.

La primera línea ( HTTP/1.1 200 OK) contiene el código de respuesta , en este caso es 200 OK. Significa que el servidor ha decidido que puede devolver un documento, según lo solicitado, y promete que el contenido que sigue será dicho documento. Si este no es el caso, el código será otra cosa y proporcionará alguna indicación de la razón por la que el servidor no solo devuelve un documento como respuesta: por ejemplo, si no puede encontrar el documento solicitado, se supone que debe devolver 404 Not Found, y si no se le permite acceder al contenido en cuestión, se supone que debe regresar 403 Forbidden.

Después de esta primera línea de estado, siguen los encabezados de respuesta; proporcionan más información sobre el contenido que se devuelve, como su contenido Content-type.

Lo siguiente es una línea vacía. Señala el hecho de que no seguirán más encabezados de respuesta. Todo lo que pase de esa línea es el contenido del documento que solicitó. Entonces, en el ejemplo anterior, <!DOCTYPE html>es la primera línea de la página de inicio de SuperUser (un documento HTML). Si estuviera solicitando un documento para descargar, probablemente serían algunos caracteres galimatías, porque la mayoría de los formatos de documentos son ilegibles sin procesamiento previo.

De vuelta a los encabezados. La más interesante para nosotros es la última, Content-Length. Informa al navegador cuántos bytes de datos debe esperar después de la línea vacía, por lo que básicamente es el tamaño del documento expresado en bytes. Este encabezado no es obligatorio y puede ser omitido por el servidor. A veces, el tamaño del documento no se puede predecir (por ejemplo, cuando el documento se genera sobre la marcha), a veces los programadores perezosos no lo incluyen (bastante común en los sitios de descarga de controladores), a veces los sitios web son creados por novatos que no saben de tal encabezado.

De todos modos, sea cual sea el motivo, puede faltar el encabezado. En ese caso, el navegador no sabe cuántos datos enviará el servidor y, por lo tanto, muestra el tamaño del documento como desconocido , esperando que el servidor cierre la conexión. Y esa es la razón de los tamaños de documentos desconocidos.


44
Una nota muy, muy menor: los navegadores admiten protocolos distintos de HTTP. Pero otros protocolos son raros en estos días, y esencialmente los mismos conceptos se aplican a otros protocolos a pesar de que los detalles son diferentes.
Robert Fisher

55
@RobertFisher FTP es un protocolo raro? : p
Thomas

55
@Thomas Esa es mi experiencia en estos días. Han pasado varios años desde que recuerdo haber visto una URL ftp en mi navegador. Hace unos años estaba usando ftp, directamente en lugar de con un navegador, en el trabajo (casi por completo), pero scp maneja esas tareas ahora. Lo único que uso ftp para hoy es subir contenido a un servidor web minimalista. Por supuesto, YMMV. ^ _ ^
Robert Fisher

2
Este es exactamente el tipo de respuesta que me hace amar este sitio. ¿Cómo le otorgo una recompensa?
Ese chico brasileño

1
@ ruda.almeida de ustedes no está de acuerdo con eso, puede publicar sobre eso en meta.superuser.com, se discutirá y tal vez alguien vuelva a abrir la pregunta.
gronostaj

54

El Content-Lengthencabezado HTTP es opcional en algunos casos y, como tal, no se puede transmitir con el archivo; el final del archivo se señalará cuando se cierre el socket.


1
Para ser precisos, HTTP 1.0 definió la longitud del contenido cerrando el socket después de cada documento. Esto todavía es compatible con HTTP 1.1 por compatibilidad. Pero HTTP 1.1 permite reutilizar conexiones para múltiples documentos si Content-Lengthse usa el campo de encabezado o si se transfiere el documento Transfer-Encoding: chunked. Este último permite generar dinámicamente contenido y enviarlo por partes a medida que se genera y puede señalar el final del documento.
x4u

3

Cuando el contenido (por ejemplo, un .pdfdocumento o una hoja de Excel) se crea sobre la marcha, el tamaño no se puede conocer antes. En estos casos, el servidor no puede enviarle el tamaño de la descarga antes y el navegador no puede mostrar el tamaño total.


99
@alfo tendrá que estar en desacuerdo ... si estoy transmitiendo video, o incluso si estoy transmitiendo cualquier tipo de datos que no sea de un tamaño fijo, si el punto es llevar los datos al usuario lo más rápido posible, No sabré el tamaño en el punto donde comienzo la transmisión
Foon

44
@Alfo Puede crear datos como .pdfarchivos sobre la marcha. Mientras los datos no se escriban de manera completa, no conoce el tamaño, pero ya puede enviar el ata al navegador. Ya hice esto en Java y envié un archivo de Excel al navegador que se generó sobre la marcha. Desde el lado de los navegadores, parecía una descarga, pero desde el lado de los servidores es una transmisión. Por lo tanto, es posible transmitir .pdf archivos incluso si no puede imaginar esto. Desde el navegador parece una descarga sin duración conocida.
Uwe Plonus

8
@Alfo: solo necesita terminar de crearse antes de enviar el último paquete al cliente.
GalacticCowboy

44
@Alfo Nunca he tomado información sobre la transmisión de videos, sino sobre la transmisión en general, ¡que también puede transmitir un .pdfarchivo o una hoja de Excel!
Uwe Plonus

2
@Alfo: tiene un punto válido, los archivos dinámicos pueden crearse por completo primero en la memoria y luego enviarse a través de HTTP y es fácil de calcular la longitud del contenido. Sin embargo, si el servidor está enviando muchos archivos grandes creados dinámicamente que se dividirán en muchos paquetes, tiene sentido que el servidor simplemente comience a enviar los fragmentos a medida que se calculan (en lugar de tener que crear cada archivo grande en la memoria y luego mándalo). HTTP 1.1 diseñó específicamente la codificación de transferencia fragmentada para este propósito.
dr jimbob
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.