Спецификация протокола возобновляемой загрузки файлов через HTTP

Валерий Холодков <valery@grid.net.ru>, 2010

1. Введение

Этот документ описывает прикладной протокол, которые используется в nginx upload module для реализации возобновляемой загрузки файлов. Первая версия модуля, поддерживающая этот протокол -- 2.2.0.

2. Назначение

Протокол HTTP реализует загрузку файлов в теле запроса с инкапсуляцией согласно RFC 1867. Если длина тела запроса черезвычайно большая, то велика вероятность обрыва соединения в процессе передачи запроса на сервер. HTTP не предусматривает механизма возобновления прерванного запроса. Задача описываемого протокола заключается в реализации механизма возобновления прерванной передачи файла после обрыва соединения или останова загрузки по требованию пользователя.

2.1. Разбиение файлов на сегменты

В случае аварийного обрыва TCP-соединения нет возможности достоверно определить какая часть потока данных была успешно доставлена, а какая -- нет. В связи с этим, клиент не может определить с какой позиции возобновить загрузку без обращения к серверу. Для устранения дополнительного обращения к серверу файл представляется в виде массива сегментов умеренной длины. В случае обрыва соединения при передаче некоторого сегмента клиент повторяет передачу всего сегмента до получения позитивного ответа от сервера, либо достижения максимального числа попыток. В рамках описываемого протокола клиент отвечает за подбор оптимальной длины сегмента.

Для отслеживания прогресса передачи файла клиент и сервер адресуют каждый байт файла идентичным образом. Первый байт файла имеет номер 0, последний байт файла имеет номер n-1, где n -- длина файла в байтах.

Порядок передачи сегментов не определен и выбирается клиентом произвольно. Однако, рекомендуется передавать сегменты в порядке возрастания номеров байт файла. Кроме того, клиент может принять решение передавать несколько сегментов одновременно, используя несколько независимых соединений. Если клиент превышает максимальное число одновременных соединений разрешенных сервером, сервер может вернуть ответ с кодом 503 Service Unavailable.

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

2.2. Инкапсуляция

Каждый сегмент файла передается отдельным HTTP-запросом. Используется метод POST. Каждый запрос содержит следующие специфичные заголовки:

Имя заголовкаЗначение
Content-Dispositionattachment, filename="имя загружаемого файла"
Content-Typemime-тип загружаемого файла (должет отличаться от multipart/form-data);
X-Content-Range
или
Content-Range
диапазон байт загружаемого сегмента;
X-Session-ID
или
Session-ID
идентификатор сессии загружаемого файла (см. 2.3);

Тело запроса должно содержать сегмент файла, соответствующий диапазону, объявленному в заголовках X-Content-Range или Content-Range.

Если клиенту не удается установить mime-тип загружаемого файла, то он может использовать тип application/octet-stream.

2.3. Управление сессиями

Для идентификации запросов, содержащих сегменты одного файла, клиент передает уникальный идентификатор сессии в заголовках X-Session-ID или Session-ID. Клиент отвечает за уникальность идентификатора сессии. Сервер должен быть готов обработать запросы, приходящие с различных IP-адресов, но принадлежащие одной сессии.

2.4. Подтверждение

Сервер подтверждает получение каждого сегмента позитивным ответом. Позитивными ответами считаются: 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

<тело ответа>