Почему некоторые загружаемые файлы не имеют собственного размера? [Дубликат]


82

На этот вопрос уже есть ответ здесь:

Иногда при загрузке файла в веб-браузер процесс загрузки не «знает» общий размер файла или его длительность - он просто показывает скорость его загрузки с Всего как «Неизвестно».

Почему браузер не знает окончательный размер некоторых файлов? Откуда он берет эту информацию в первую очередь?


13
Динамически созданные файлы не имеют размера, они передаются в виде потока до достижения EOF.
Fiasco Labs

Ответы:


114

Для запроса документов с веб-серверов браузеры используют протокол HTTP. Возможно, вы знаете это имя из адресной строки (оно может быть скрыто сейчас, но когда вы щелкнете по адресной строке, скопируете URL-адрес и вставите его в какой-нибудь текстовый редактор, вы увидите его http://в начале). HTTP - это простой текстовый протокол. Это работает так:

Во-первых, ваш браузер подключается к серверу веб-сайта и отправляет URL-адрес документа, который он хочет загрузить (веб-страницы также являются документами), а также некоторые сведения о самом браузере ( User-Agent и т. Д.). Например, чтобы загрузить главную страницу на сайте SuperUser http://superuser.com/, мой браузер отправляет запрос, который выглядит следующим образом:

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

Первая строка указывает, какой документ сервер должен вернуть. Другие строки называются заголовками; они выглядят так:

Header name: Header value

Эти строки отправляют дополнительную информацию, которая помогает серверу решить, что делать.

Если все хорошо, сервер ответит отправкой запрошенного документа. Ответ начинается с сообщения о состоянии, за которым следуют некоторые заголовки (с подробной информацией о документе) и, наконец, если все хорошо, содержимое документа. Вот как выглядит ответ сервера SuperUser на мой запрос:

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>

После последней строки сервер SuperUser закрывает соединение.

Первая строка ( HTTP/1.1 200 OK) содержит код ответа , в данном случае это 200 OK. Это означает, что сервер решил, что он может вернуть документ в соответствии с запросом, и обещает, что последующее содержимое будет таким документом. Если это не тот случай, код будет чем-то другим, и он предоставит некоторое указание причины, по которой сервер не просто возвращает документ в качестве ответа: например, если он не может найти запрошенный документ, он должен вернуть 404 Not Foundи если вам не разрешен доступ к рассматриваемому контенту, он должен вернуться 403 Forbidden.

После этой первой строки состояния следуют заголовки ответа; они предоставляют больше информации о возвращаемом контенте, например, его Content-type.

Следующая пустая строка. Это сигнализирует о том, что больше не будет заголовков ответа. Все, что за этой строкой, является содержанием запрошенного документа. Таким образом, в приведенном выше примере <!DOCTYPE html>это первая строка домашней страницы SuperUser (HTML-документ). Если бы я запрашивал документ для загрузки, это, вероятно, были бы некоторые бессмысленные символы, потому что большинство форматов документов не читаются без предварительной обработки.

Вернуться к заголовкам. Самый интересный для нас - последний Content-Length. Он сообщает браузеру, сколько байтов данных следует ожидать после пустой строки, поэтому в основном это размер документа, выраженный в байтах. Этот заголовок не является обязательным и может быть опущен сервером. Иногда размер документа не может быть предсказан (например, когда документ генерируется на лету), иногда ленивые программисты не включают его (довольно часто на сайтах загрузки драйверов), иногда сайты создаются новичками, которые не знают такого заголовка.

В любом случае, какой бы ни была причина, заголовок может отсутствовать. В этом случае браузер не знает, сколько данных сервер собирается отправить, и поэтому отображает размер документа как неизвестный , ожидая, пока сервер закроет соединение. И это причина неизвестных размеров документов.


4
Очень, очень незначительное замечание: браузеры поддерживают протоколы, отличные от HTTP. Но другие протоколы в наши дни редки, и, по сути, те же концепции применимы к другим протоколам, хотя детали отличаются.
Роберт Фишер

5
@RobertFisher FTP - это редкий протокол? : p
Томас

5
@ Томас Это мой опыт в эти дни. Прошло несколько лет с тех пор, как я помню URL-адрес FTP в моем браузере Несколько лет назад я использовал ftp - напрямую, а не с браузером - на работе (почти полностью загружал), но эти задачи теперь выполняются scp. На сегодняшний день я использую только ftp, загружая контент на минималистичный веб-хостинг. Конечно, YMMV. ^ _ ^
Роберт Фишер

2
Это именно тот ответ, который заставляет меня любить этот сайт. Как я могу предоставить это вознаграждение?
Этот бразильский парень

1
@ ruda.almeida вы с этим не согласны, вы можете опубликовать об этом на meta.superuser.com, это будет обсуждаться, и, возможно, кто-то снова откроет вопрос.
Гроностай

54

Content-LengthЗаголовок HTTP является необязательным в некоторых случаях и как таковой он может не передаваться вместе с файлом; конец файла будет сигнализироваться при закрытии сокета.


1
Чтобы быть точным, HTTP 1.0 определял длину содержимого, закрывая сокет после каждого документа. Это все еще поддерживается в HTTP 1.1 для совместимости. Но HTTP 1.1 позволяет повторно использовать соединения для нескольких документов, если либо используется Content-Lengthполе заголовка, либо документ переносится с Transfer-Encoding: chunked. Последний позволяет динамически генерировать контент и отправлять его по кусочкам, когда он генерируется, и может сигнализировать об окончании документа.
x4u

3

Когда содержимое (например, .pdfдокумент или лист Excel) создается на лету, размер не может быть известен раньше. В этом случае сервер не может отправить вам размер загрузки ранее, а браузер не может отобразить общий размер.


9
@alfo будет вынужден не согласиться ... если я транслирую видео, или даже если я транслирую любые данные, которые не имеют фиксированный размер, если цель состоит в том, чтобы передать данные пользователю как можно быстрее, Я не буду знать размер в том месте, где я начну передачу
Foon

4
@Alfo Вы можете создавать данные как .pdfфайлы на лету. Пока данные записаны не полностью, вы не знаете их размера, но вы можете отправить ata уже в браузер. Я сделал это уже на Java и отправил файл Excel в браузер, который генерируется на лету. Со стороны браузеров это выглядело как загрузка, а со стороны серверов - потоковое. Таким образом, возможно потоковое воспроизведение .pdf файлов, даже если вы не можете себе этого представить. Из браузера это выглядит как загрузка без известной длины.
Уве Плонус

8
@Alfo - его нужно только завершить, прежде чем последний пакет будет отправлен клиенту.
GalacticCowboy

4
@Alfo Я никогда не думал о пропарке видео, а о потоковой передаче в целом, которая также может быть потоковой передачей .pdfфайла или листа Excel!
Уве Плонус

2
@Alfo - у вас есть правильная точка, динамические файлы могут быть полностью созданы сначала в памяти, а затем отправлены через HTTP и легко рассчитать длину содержимого. Однако, если сервер отправляет много больших динамически создаваемых файлов, которые будут разбиты на множество пакетов, для сервера имеет смысл просто начать отправлять порции по мере их вычисления (вместо необходимости создавать каждый большой файл в памяти, а затем Отправь это). Для этой цели в HTTP 1.1 специально разработана кодировка передачи по частям.
Доктор Джимбоб
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.