Валерий Холодков <valery@grid.net.ru>, 2010
Этот документ описывает прикладной протокол, которые используется в nginx upload module для реализации возобновляемой загрузки файлов. Первая версия модуля, поддерживающая этот протокол -- 2.2.0.
Протокол HTTP реализует загрузку файлов в теле запроса с инкапсуляцией согласно RFC 1867. Если длина тела запроса черезвычайно большая, то велика вероятность обрыва соединения в процессе передачи запроса на сервер. HTTP не предусматривает механизма возобновления прерванного запроса. Задача описываемого протокола заключается в реализации механизма возобновления прерванной передачи файла после обрыва соединения или останова загрузки по требованию пользователя.
В случае аварийного обрыва TCP-соединения нет возможности достоверно определить какая часть потока данных была успешно доставлена, а какая -- нет. В связи с этим, клиент не может определить с какой позиции возобновить загрузку без обращения к серверу. Для устранения дополнительного обращения к серверу файл представляется в виде массива сегментов умеренной длины. В случае обрыва соединения при передаче некоторого сегмента клиент повторяет передачу всего сегмента до получения позитивного ответа от сервера, либо достижения максимального числа попыток. В рамках описываемого протокола клиент отвечает за подбор оптимальной длины сегмента.
Для отслеживания прогресса передачи файла клиент и сервер адресуют каждый байт файла идентичным образом. Первый байт файла имеет номер 0, последний байт файла имеет номер n-1, где n -- длина файла в байтах.
Порядок передачи сегментов не определен и выбирается клиентом произвольно. Однако, рекомендуется передавать сегменты в порядке возрастания номеров байт файла. Кроме того, клиент может принять решение передавать несколько сегментов одновременно, используя несколько независимых соединений. Если клиент превышает максимальное число одновременных соединений разрешенных сервером, сервер может вернуть ответ с кодом 503 Service Unavailable.
В случае одновременной передачи сегментов, внутри сеанса передачи одного файла клиенту запрещено отправлять два или более запросов с пересекающимися диапазонами. В случае обнаружения одновременных запросов с пересекающимися диапазонами сервер должен вернуть ошибочный ответ.
Каждый сегмент файла передается отдельным HTTP-запросом. Используется метод POST. Каждый запрос содержит следующие специфичные заголовки:
Имя заголовка | Значение |
---|---|
Content-Disposition | attachment, filename="имя загружаемого файла" |
Content-Type | mime-тип загружаемого файла (должет отличаться от multipart/form-data); |
X-Content-Range или Content-Range | диапазон байт загружаемого сегмента; | X-Session-ID или Session-ID | идентификатор сессии загружаемого файла (см. 2.3); |
Тело запроса должно содержать сегмент файла, соответствующий диапазону, объявленному в заголовках X-Content-Range или Content-Range.
Если клиенту не удается установить mime-тип загружаемого файла, то он может использовать тип application/octet-stream.
Для идентификации запросов, содержащих сегменты одного файла, клиент передает уникальный идентификатор сессии в заголовках X-Session-ID или Session-ID. Клиент отвечает за уникальность идентификатора сессии. Сервер должен быть готов обработать запросы, приходящие с различных IP-адресов, но принадлежащие одной сессии.
Сервер подтверждает получение каждого сегмента позитивным ответом. Позитивными ответами считаются: 201 Created если на момент генерации ответа были получены не все сегменты файла или все остальные 2xx и 3xx ответы, если на момент генерации ответа были получены все сегменты файла. Сервер может вернуть позитивный ответ только в том случае, если все байты сегмента были успешно сохранены и информация о том, какие диапазоны байт уже приняты была успешно обновлена.
При получении ответа 201 Created клиент должен перейти к отправке следующего сегмента. При получении всех остальных позитивных ответов клиент должен действовать согласно их стандартной интерпретации (см. RFC 2616).
В каждом ответе 201 Created сервер возвращает заголовок Range содержащий перечисление всех диапазонов файла, которые были получены на момент генерации ответа. Сервер дублирует идентичный список диапазонов в теле ответа.
Пример 1: Запрос клиента, содержащий первый сегмент файла
POST /upload HTTP/1.1 Host: example.com Content-Length: 51201 Content-Type: application/octet-stream Content-Disposition: attachment; filename="big.TXT" X-Content-Range: bytes 0-51200/511920 Session-ID: 1111215056 <байты 0-51200>
Пример 2: Ответ сервера на запрос, содержащий первый сегмент файла
HTTP/1.1 201 Created Date: Thu, 02 Sep 2010 12:54:40 GMT Content-Length: 14 Connection: close Range: 0-51200/511920 0-51200/511920
Пример 3: Запрос клиента, содержащий последний сегмент файла
POST /upload HTTP/1.1 Host: example.com Content-Length: 51111 Content-Type: application/octet-stream Content-Disposition: attachment; filename="big.TXT" X-Content-Range: bytes 460809-511919/511920 Session-ID: 1111215056 <байты 460809-511919>
Пример 4: Ответ сервера на запрос, содержащий последний сегмент файла
HTTP/1.1 200 OK Date: Thu, 02 Sep 2010 12:54:43 GMT Content-Type: text/html Connection: close Content-Length: 2270 <тело ответа>