Возобновляемые загрузки

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

Возобновляемая загрузка особенно полезна в следующих случаях:

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

В этом руководстве описана последовательность HTTP-запросов, которые приложение выполняет для загрузки видео с использованием возобновляемой загрузки. Это руководство предназначено в первую очередь для разработчиков, которые не могут использовать клиентские библиотеки Google API, некоторые из которых обеспечивают встроенную поддержку возобновляемых загрузок. В руководстве по загрузке видео с помощью YouTube Data API рассказывается, как использовать клиентскую библиотеку API Google для Python, чтобы загружать видео с возможностью возобновления.

Примечание. Вы также можете посмотреть последовательность запросов, сделанных для возобновляемой загрузки или любой другой операции API, используя одну из клиентских библиотек API Google с включенным ведением журнала HTTPS. Например, чтобы включить трассировку HTTP для Python, используйте библиотеку httplib2:

httplib2.debuglevel = 4

Шаг 1. Начните сеанс с возможностью возобновления

Чтобы начать возобновляемую загрузку видео, отправьте запрос POST на следующий URL: В URL задайте для параметра part значение параметра, подходящее для вашего запроса. Помните, что значение параметра определяет части, содержащие свойства, которые вы задаете, а также части, которые вы хотите включить в ответ API. Значения параметров в URL запроса должны быть закодированы.

https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS

В теле запроса укажите ресурс video. Также задайте следующие заголовки HTTP-запросов:

  • Authorization – токен авторизации для запроса.
  • Content-Length – количество байтов в теле запроса. Если вы используете поблочное кодирование передачи, указывать этот заголовок не нужно.
  • Content-Type – задайте значение application/json; charset=UTF-8.
  • X-Upload-Content-Length – количество байтов, которые будут загружены в последующих запросах. Укажите размер загружаемого файла.
  • x-upload-content-type – MIME-тип загружаемого файла. Вы можете загружать файлы с любым MIME-типом видео (video/*) или MIME-типом application/octet-stream.

В примере ниже показано, как инициировать возобновляемый сеанс для загрузки видео. Запрос задает (и будет получать) свойства в частях snippet и status ресурса video, а также будет получать свойства в части contentdetails ресурса.

post /upload/youtube/v3/videos?uploadType=resumable&part=parts http/1.1
host: www.googleapis.com
authorization: bearer auth_token
content-length: content_length
content-type: application/json; charset=utf-8
x-upload-content-length: x_upload_content_length
X-Upload-Content-Type: X_UPLOAD_CONTENT_TYPE

video resource

В следующем примере показан запрос POST, в котором заполнены все эти значения, кроме токена аутентификации. Значение categoryId в примере соответствует категории видео. Список поддерживаемых категорий можно получить с помощью метода videoCategories.list API.

POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer AUTH_TOKEN
Content-Length: 278
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Length: 3000000
X-Upload-Content-Type: video/*

{
  "snippet": {
    "title": "My video title",
    "description": "This is a description of my video",
    "tags": ["cool", "video", "more keywords"],
    "categoryId": 22
  },
  "status": {
    "privacyStatus": "public",
    "embeddable": True,
    "license": "youtube"
  }
}

Шаг 2. Сохраните URI сеанса с возможностью возобновления

Если запрос будет выполнен успешно, сервер API ответит кодом статуса HTTP 200 (OK), а в ответе будет заголовок HTTP Location, в котором указан URI для сеанса с возможностью возобновления. Этот URI вы будете использовать для загрузки видеофайла.

Ниже приведен пример ответа API на запрос, описанный на шаге 1.

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
Content-Length: 0

Шаг 3. Загрузите видеофайл

После извлечения URI сеанса из ответа API вам нужно загрузить контент видеофайла в это местоположение. Тело запроса – это содержимое двоичного файла для загружаемого видео. Ниже показан формат запроса.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: CONTENT_LENGTH
Content-Type: CONTENT_TYPE

BINARY_FILE_DATA

В запросе задаются следующие заголовки HTTP-запроса:

  • Authorization – токен авторизации для запроса.
  • Content-Length – размер загружаемого файла. Это значение должно совпадать со значением заголовка HTTP-запроса X-Upload-Content-Length, указанным на шаге 1.
  • Content-Type – MIME-тип загружаемого файла. Это значение должно совпадать со значением заголовка HTTP-запроса X-Upload-Content-Type на шаге 1.

Шаг 4. Завершите загрузку видео

Ваш запрос приведет к одному из следующих сценариев:

  • Загрузка выполнена.

    Сервер API отвечает кодом ответа HTTP 201 (Created). Тело ответа – это созданный вами ресурс video.

  • Загрузка не удалась, но ее можно возобновить.

    Возобновить загрузку можно в следующих случаях:

    • Ваш запрос прерван, так как подключение между приложением и сервером API потеряно. В этом случае вы не получите ответ API.

    • В ответе API указан один из следующих кодов ответа 5xx. При возобновлении загрузки после получения любого из этих кодов ответа в вашем коде должна использоваться стратегия экспоненциальной выдержки.

      • 500 – Internal Server Error
      • 502 – Bad Gateway
      • 503 – Service Unavailable
      • 504 – Gateway Timeout

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

  • Не удалось загрузить файл.

    Если загрузка не удалась, ответ содержит сообщение об ошибке, которое помогает понять причину сбоя. Если загрузка не удалась окончательно, в ответе API будет код ответа 4xx или 5xx, отличный от перечисленных выше.

    Если вы отправите запрос с URI сеанса, срок действия которого истек, сервер вернет код HTTP-ответа 404 (Not Found). В этом случае вам нужно будет начать новую возобновляемую загрузку, получить новый URI сеанса и начать загрузку с начала, используя новый URI.

Шаг 4.1. Проверьте статус загрузки

Чтобы проверить статус прерванной возобновляемой загрузки, отправьте пустой запрос PUT на URL загрузки, полученный на шаге 2 и использованный на шаге 3. В запросе установите для заголовка Content-Range значение bytes */CONTENT_LENGTH, где CONTENT_LENGTH – размер загружаемого файла.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 0
Content-Range: bytes */CONTENT_LENGTH

Шаг 4.2. Обработайте ответ API

Если загрузка уже завершена, независимо от того, была ли она успешной, API вернет тот же ответ, который был отправлен при завершении загрузки.

Если загрузка была прервана или ещё не завершена, API вернет код ответа HTTP 308 (Resume Incomplete). В ответе заголовок Range указывает, сколько байтов файла уже успешно загружено.

  • Значение заголовка индексируется с 0. Таким образом, значение заголовка 0-999999 указывает, что были загружены первые 1,000,000 байт файла.
  • Если ничего не загружено, ответ API не будет содержать заголовок Range.

Ниже приведен пример ответа API для возобновляемой загрузки.

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-999999

Если в ответе API также есть заголовок Retry-After, используйте его значение, чтобы определить, когда можно попытаться возобновить загрузку.

Шаг 4.3. Возобновите загрузку

Чтобы возобновить загрузку, отправьте ещё один запрос PUT на URL загрузки, полученный на шаге 2. В теле запроса укажите двоичный код для той части видеофайла, которая ещё не была загружена.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: REMAINING_CONTENT_LENGTH
Content-Range: bytes FIRST_BYTE-LAST_BYTE/TOTAL_CONTENT_LENGTH

PARTIAL_BINARY_FILE_DATA

Вам нужно задать следующие заголовки HTTP-запроса:

  • Authorization – токен авторизации для запроса.

  • Content-Length – размер в байтах контента, который ещё не был загружен. Если вы загружаете остаток файла, то можете рассчитать это значение, вычтя значение FIRST_BYTE из значения TOTAL_CONTENT_LENGTH. Оба значения используются в заголовке Content-Range.

  • Content-Range – часть файла, которую вы загружаете. Значение заголовка состоит из трех частей:

    • FIRST_BYTE – числовой индекс байта, с которого нужно возобновить загрузку. Нумерация начинается с нуля. Это значение на единицу больше второго числа в заголовке Range, полученном на предыдущем шаге. В приведенном выше примере значение заголовка Range было 0-999999, поэтому первый байт в последующей возобновленной загрузке будет 1000000.

    • LAST_BYTE – числовой индекс последнего байта загружаемого двоичного файла. Нумерация начинается с 0. Обычно это последний байт в файле. Например, если размер файла составляет 3000000 байт, то последний байт в файле будет иметь номер 2999999.

    • TOTAL_CONTENT_LENGTH – общий размер видеофайла в байтах. Это значение совпадает с заголовком Content-Length, указанным в исходном запросе на загрузку.

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

    Таким образом, первый байт, загруженный при возобновлении загрузки, должен быть следующим байтом после последнего байта, который уже был успешно загружен на YouTube. Подробнее о заголовке Range рассказывается в шаге 4.2.

    Таким образом, если последний байт в заголовке Range – 999999, то первым байтом в запросе на возобновление загрузки должен быть байт 1000000. (Нумерация начинается с 0.) Если вы попытаетесь возобновить загрузку с байта 999999 или меньшего (перекрывающиеся байты) или с байта 1000001 или большего (пропущенные байты), двоичный контент не будет загружен.

Как загрузить файл по частям

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

Инструкции по загрузке файла по частям практически идентичны четырехэтапному процессу, описанному ранее в этом руководстве. Однако запросы на начало загрузки файла (шаг 3 выше) и на возобновление загрузки (шаг 4.3 выше) устанавливают значения заголовков Content-Length и Content-Range по-разному, когда файл загружается по частям.

  • Значение заголовка Content-Length указывает размер фрагмента, который отправляет запрос. Обратите внимание на следующие ограничения размера фрагментов:

    • Размер фрагмента должен быть кратен 256 КБ. Это ограничение не относится к последнему фрагменту, поскольку размер всего файла может быть не кратен 256 КБ. Помните, что чем больше фрагменты, тем эффективнее загрузка.

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

  • Заголовок Content-Range указывает, какие байты файла загружаются в запросе. При настройке этого значения можно использовать инструкции по настройке заголовка Content-Range из шага 4.3.

    Например, значение bytes 0-524287/2000000 указывает, что запрос отправляет первые 524 288 байт (256 x 2048) в файле размером 2 000 000 байт.

В примере ниже показан формат первого из серии запросов, которые будут загружать файл размером 2 000 000 байт по частям:

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 524888
Content-Type: video/*
Content-Range: bytes 0-524287/2000000

{bytes 0-524287}

Если запрос, не являющийся последним, выполнен успешно, сервер API возвращает ответ 308 (Resume Incomplete). Формат ответа будет таким же, как описано выше в разделе Шаг 4.2. Обработка ответа API.

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

Когда файл будет загружен полностью, сервер вернет код ответа HTTP 201 (Created) и запрошенные части созданного видеоресурса.

Если запрос прерван или приложение получило код ответа 5xx, выполните процедуру, описанную в шаге 4, чтобы завершить загрузку. Однако вместо того, чтобы пытаться загрузить оставшуюся часть файла, просто продолжайте загружать фрагменты с того места, где вы возобновляете загрузку. Проверьте статус загрузки, чтобы определить, с какого места ее нужно возобновить. Не предполагайте, что сервер получил все (или ни одного) байты, отправленные в предыдущем запросе.

Примечание. Вы также можете запросить статус активной загрузки между загруженными фрагментами. (Для получения статуса загрузки не обязательно, чтобы она была прервана.)