Чому деякі завантажуючі файли не знають власного розміру? [дублікат]


82

На це питання вже є відповідь тут:

Іноді під час завантаження файлу у веб-браузері прогрес завантаження не "знає" загальний розмір файлу або наскільки далеко він у завантаженні - він просто показує швидкість, з якою завантажується, загалом як "Невідомо".

Чому браузер не знає остаточний розмір деяких файлів? Звідки в першу чергу береться ця інформація?


13
Динамічно створені файли не мають розміру, вони надходять як потік до досягнення EOF.
Лабораторії Фіаско

Відповіді:


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
@Thomas Такий мій досвід в наші дні. Минуло кілька років, як я пам'ятаю, як у своєму браузері бачив ftp URL. Кілька років тому я використовував ftp - безпосередньо, а не з браузером - на роботі (майже повністю завантажуючи), але ці завдання зараз вирішує scp. Єдине, що я сьогодні використовую ftp, це завантаження вмісту на мінімалістичний веб-хост. Звичайно, YMMV. ^ _ ^
Роберт Фішер

2
Саме ця відповідь змушує мене любити цей сайт. Як я можу надати йому винагороду?
Той бразильський хлопець

1
@ ruda.almeida ви не згодні з цим, ви можете розмістити інформацію про це на meta.superuser.com, це буде обговорено, і, можливо, хтось знову відкриє питання.
gronostaj

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файли на льоту. Поки дані не записані на конкуренції, ви не знаєте розміру, але ви можете відправити ата вже в браузер. Я вже робив це на Java і надіслав у браузер файл Excel, який як генерується на льоту. З боку браузерів це виглядало як завантаження, але з боку серверів - це потокове передавання. Тому можна передавати .pdf файли, навіть якщо ви цього не уявляєте. З браузера це схоже на завантаження без відомої довжини.
Uwe Plonus

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

4
@Alfo Я ніколи не taked про відео пропарювання , а про потоковому в цілому, що також може бути потокового .pdfфайлу або лист Excel!
Uwe Plonus

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