API для публикации игровых сервисов Play Games позволяет загружать изображение для игрового ресурса.
Варианты загрузки
API для публикации игр от Play Games Services позволяет загружать определенные типы бинарных данных или медиафайлов. Конкретные характеристики загружаемых данных указаны на справочной странице для каждого метода, поддерживающего загрузку медиафайлов:
Максимальный размер загружаемого файла : максимальный объем данных, который можно сохранить этим методом.
Допустимые MIME-типы носителей : типы двоичных данных, которые можно хранить с помощью этого метода.
Вы можете отправлять запросы на загрузку любым из следующих способов. Укажите используемый метод с помощью параметра запроса uploadType.
Простая загрузка :
uploadType=media. Для быстрой передачи небольших файлов, например, размером 5 МБ или меньше.Многокомпонентная загрузка :
uploadType=multipart. Для быстрой передачи небольших файлов и метаданных; передает файл вместе с описывающими его метаданными в одном запросе.Возобновляемая загрузка :
uploadType=resumable. Для надежной передачи, особенно важной для больших файлов. При этом методе используется запрос на инициацию сессии, который может дополнительно включать метаданные. Это хорошая стратегия для большинства приложений, поскольку она работает и для небольших файлов, но требует одного дополнительного HTTP-запроса на каждую загрузку.
При загрузке медиафайлов используется специальный URI. Фактически, методы, поддерживающие загрузку медиафайлов, имеют два конечных URI:
URI /upload используется для загрузки медиафайлов . Формат конечной точки загрузки — стандартный URI ресурса с префиксом «/upload». Используйте этот URI при передаче самих медиаданных.
Пример:
POST /upload/games/v1configuration/images/resourceId/imageType/imageTypeСтандартный URI ресурса для метаданных . Если ресурс содержит какие-либо поля данных, эти поля используются для хранения метаданных, описывающих загруженный файл. Вы можете использовать этот URI при создании или обновлении значений метаданных.
Пример:
POST /games/v1configuration/images/resourceId/imageType/imageType
Простая загрузка
Самый простой способ загрузки файла — это отправка простого запроса на загрузку. Этот вариант является хорошим выбором, если выполняется одно из следующих условий:
Размер файла достаточно мал, чтобы при сбое соединения его можно было загрузить целиком повторно.
Метаданные для отправки отсутствуют. Это может быть так, если вы планируете отправлять метаданные для этого ресурса в отдельном запросе или если метаданные не поддерживаются или недоступны. Для использования простой загрузки отправьте POST или PUT запрос к URI метода /upload и добавьте параметр запроса uploadType=media. Например:
POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media
При выполнении простого запроса на загрузку следует использовать следующие HTTP-заголовки:
Content-Type. Установите один из типов медиаданных для загрузки, принимаемых методом, как указано в справочнике по API публикации.Content-Length. Установите значение, равное количеству загружаемых байтов. Не требуется, если вы используете кодирование с пошаговой передачей .
Пример: Простая загрузка
В следующем примере показано использование простого запроса на загрузку данных через API публикации сервисов Play Games.
POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: image/png
Content-Length: number_of_bytes_in_file
Authorization: Bearer your_auth_token
PNG data
Если запрос выполнен успешно, сервер возвращает код состояния HTTP 200 OK вместе со всеми метаданными. Например:
HTTP/1.1 200
Content-Type: application/json
{
"kind": "gamesConfiguration#imageConfiguration",
"url": string,
"resourceId": string,
"imageType": string
}
Многокомпонентная загрузка
Если вам необходимо отправить метаданные вместе с данными для загрузки, вы можете выполнить один multipart/related запрос. Это хороший вариант, если отправляемые данные достаточно малы, чтобы их можно было загрузить целиком повторно в случае сбоя соединения.
Для использования многокомпонентной загрузки отправьте POST или PUT запрос к URI метода /upload и добавьте параметр запроса uploadType=multipart . Например:
POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart
В качестве основных HTTP-заголовков для многокомпонентной загрузки следует использовать следующие:
- Content-Type . Установите значение multipart/related и укажите разделительную строку, используемую для идентификации частей запроса.
- Content-Length . Устанавливается равным общему количеству байтов в теле запроса. Медиаконтент запроса должен быть меньше максимального размера файла, указанного для этого метода.
Тело запроса отформатировано как многокомпонентный/связанный контент типа RFC2387 и содержит ровно две части. Части идентифицируются разделительной строкой, за которой следуют два дефиса.
Каждая часть многокомпонентного запроса должна содержать дополнительный заголовок Content-Type:
Метаданные : должны располагаться первыми, а Content-Type должен соответствовать одному из принятых форматов метаданных.
Часть, относящаяся к медиафайлам : должна быть указана второй, а Content-Type должен соответствовать одному из MIME-типов медиафайлов, принимаемых данным методом.
Для каждого метода см. справочник по API публикации, где указан список принимаемых MIME-типов медиафайлов и ограничения по размеру загружаемых файлов.
Пример: Многокомпонентная загрузка
В приведенном ниже примере показан многокомпонентный запрос на загрузку данных через API публикации сервисов Play Games.
POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body
--foo_bar_baz
Content-Type: application/json; charset=UTF-8
{
"kind": "gamesConfiguration#imageConfiguration",
"url": string,
"resourceId": string,
"imageType": string
}
--foo_bar_baz
Content-Type: image/png
PNG data
--foo_bar_baz--
Если запрос выполнен успешно, сервер возвращает код состояния HTTP 200 OK вместе со всеми метаданными:
HTTP/1.1 200
Content-Type: application/json
{
"kind": "gamesConfiguration#imageConfiguration",
"url": string,
"resourceId": string,
"imageType": string
}
Возобновляемая загрузка
Для более надежной загрузки файлов данных можно использовать протокол возобновляемой загрузки. Этот протокол позволяет возобновить операцию загрузки после сбоя связи, прервавшего поток данных. Он особенно полезен при передаче больших файлов, когда высока вероятность прерывания сети или другого сбоя передачи, например, при загрузке из мобильного приложения. Он также может снизить потребление полосы пропускания в случае сбоев сети, поскольку вам не нужно начинать загрузку больших файлов с самого начала.
Для использования функции возобновления загрузки необходимо выполнить следующие действия:
Начните сеанс с возможностью возобновления загрузки. Отправьте первоначальный запрос к URI загрузки, включающий метаданные, если таковые имеются.
Сохраните URI возобновляемой сессии. Сохраните URI сессии, возвращенный в ответе на первоначальный запрос; вы будете использовать его для остальных запросов в этой сессии. Загрузите файл.
Отправьте медиафайл на URI возобновляемой сессии.
Кроме того, приложения, использующие возобновляемую загрузку, должны иметь код для возобновления прерванной загрузки. Если загрузка прервана, необходимо определить, какой объем данных был успешно получен, и затем возобновить загрузку с этого момента.
Начать сессию с возможностью возобновления
Для запуска возобновляемой загрузки отправьте POST или PUT запрос к URI метода /upload и добавьте параметр запроса uploadType=resumable . Например:
POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable
В первом запросе тело либо пустое, либо содержит только метаданные; фактическое содержимое файла, который вы хотите загрузить, будет передаваться в последующих запросах.
В первоначальном запросе используйте следующие HTTP-заголовки:
X-Upload-Content-Type. Установите значение MIME-типа медиафайлов, которые будут передаваться в последующих запросах.X-Upload-Content-Length. Установите значение, равное количеству байтов данных для загрузки, которые будут переданы в последующих запросах. Если длина неизвестна на момент запроса, этот заголовок можно опустить.Если предоставляются метаданные:
Content-Type. Устанавливается в соответствии с типом данных метаданных.Content-Length. Установите значение, равное количеству байтов, указанных в теле этого первоначального запроса. Не требуется, если вы используете кодирование с пошаговой передачей .
Для каждого метода см. справочник по API публикации, где указан список принимаемых MIME-типов медиафайлов и ограничения по размеру загружаемых файлов.
Пример: Запрос на возобновление сессии
В следующем примере показано, как инициировать возобновляемую сессию для API публикации игр Play Games Services.
POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/png
X-Upload-Content-Length: 2000000
{
"kind": "gamesConfiguration#imageConfiguration",
"url": string,
"resourceId": string,
"imageType": string
}
В следующем разделе описывается, как обрабатывать полученный ответ.
Сохраните URI сессии, которую можно возобновить.
Если запрос на инициализацию сессии проходит успешно, API-сервер отвечает HTTP-статусом 200 OK . Кроме того, он предоставляет заголовок Location , указывающий URI возобновляемой сессии. Заголовок Location , показанный в примере ниже, включает в себя параметр запроса upload_id , который задает уникальный идентификатор загрузки для данной сессии.
Пример: Ответ на инициализацию возобновляемой сессии
Вот ответ на запрос из Шага 1:
HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0
Значение заголовка Location , как показано в приведенном выше примере ответа, представляет собой URI сессии, который вы будете использовать в качестве HTTP-конечной точки для фактической загрузки файла или запроса статуса загрузки.
Скопируйте и сохраните URI сессии, чтобы использовать его для последующих запросов.
Загрузите файл
Для загрузки файла отправьте PUT запрос на URI загрузки, полученный на предыдущем шаге. Формат запроса на загрузку следующий:
PUT session_uri
В HTTP-заголовках, используемых при отправке запросов на возобновление загрузки файлов, следует указать Content-Length . Установите это значение равным количеству байтов, загружаемых в этом запросе, что обычно соответствует размеру загружаемого файла.
Пример: Запрос на возобновление загрузки файла
Вот запрос на возобновление загрузки всего PNG-файла размером 2 000 000 байт для текущего примера.
PUT https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: image/png
bytes 0-1999999
Если запрос выполнен успешно, сервер отвечает HTTP 201 Created , а также любыми метаданными, связанными с этим ресурсом. Если первоначальный запрос возобновляемой сессии был PUT для обновления существующего ресурса, то в ответе об успешном выполнении будет 200 OK , а также любые метаданные, связанные с этим ресурсом.
Если запрос на загрузку прерван или вы получили HTTP 503 Service Unavailable или любой другой ответ 5xx от сервера, выполните действия, описанные в разделе "Возобновить прерванную загрузку" .
Загружайте файл по частям.
При использовании возобновляемой загрузки вы можете разбить файл на фрагменты и отправить серию запросов на последовательную загрузку каждого фрагмента. Это не самый предпочтительный подход, поскольку дополнительные запросы связаны с производительностью, и обычно он не требуется. Однако вам может потребоваться использовать разбиение на фрагменты, чтобы уменьшить объем данных, передаваемых в одном запросе. Это полезно, когда существует фиксированный временной лимит для отдельных запросов, как это справедливо для некоторых классов запросов Google App Engine. Это также позволяет, например, отображать ход загрузки для устаревших браузеров, которые по умолчанию не поддерживают отображение хода загрузки.
Если вы загружаете данные по частям, то, помимо заголовка Content-Length, необходимого для загрузки полных файлов, требуется также заголовок Content-Range:
Content-Length. Установите значение, равное размеру фрагмента, или, возможно, меньше, как это могло быть в случае последнего запроса.Content-Rangeуказывает, какие именно байты файла вы загружаете. Например,Content-Range: bytes 0-524287/2000000показывает, что вы предоставляете первые 524 288 байт (256 x 1024 x 2) из файла размером 2 000 000 байт.
Возобновить прерванную загрузку
Если запрос на загрузку прерывается до получения ответа или если вы получаете от сервера HTTP 503 Service Unavailable , вам необходимо возобновить прерванную загрузку. Для возобновления прерванной загрузки выполните следующие действия:
Запрос статуса . Чтобы узнать текущий статус загрузки, отправьте пустой
PUTзапрос на URI загрузки. В заголовке HTTP-запроса должен содержаться заголовокContent-Range, указывающий на то, что текущая позиция в файле неизвестна. Например, установитеContent-Rangeравным*/2000000если общая длина файла составляет 2 000 000 символов. Если полный размер файла неизвестен, установите Content-Range равным*/*.Получите количество загруженных байтов . Обработайте ответ на запрос состояния. Сервер использует заголовок
Rangeв своем ответе, чтобы указать, какие байты он уже получил. Например, заголовокRangeсо значением0-299999указывает на то, что были получены первые 300 000 байтов файла.Загрузите оставшиеся данные . Наконец, теперь, когда вы знаете, где возобновить запрос, отправьте оставшиеся данные или текущий фрагмент. Обратите внимание, что в любом случае оставшиеся данные необходимо рассматривать как отдельный фрагмент, поэтому при возобновлении загрузки необходимо отправить заголовок
Content-Range.
Пример: Возобновить прерванную загрузку
Запросите статус загрузки. В следующем запросе используется заголовок Content-Range, указывающий на то, что текущая позиция в файле размером 2 000 000 байт неизвестна.
PUT {session_uri} HTTP/1.1 Content-Length: 0 Content-Range: bytes */2000000Извлеките из ответа количество уже загруженных байтов. В ответе сервера используется заголовок
Range, указывающий на то, что на данный момент получены первые 43 байта файла. Используйте верхнее значение заголовка Range, чтобы определить, с какого момента следует начать возобновленную загрузку.HTTP/1.1 308 Resume Incomplete Content-Length: 0 Range: 0-42Возобновить загрузку с того места, где она была прервана. Следующий запрос возобновляет загрузку, отправляя оставшиеся байты файла, начиная с байта 43.
PUT {session_uri} HTTP/1.1 Content-Length: 1999957 Content-Range: bytes 43-1999999/2000000 bytes 43-1999999
Обработка ошибок
При загрузке медиафайлов полезно знать некоторые передовые методы обработки ошибок.
Возобновить или повторить загрузку, которая не удалась из-за прерывания соединения или ошибок 5xx, включая:
-
500 Internal Server Error -
502 Bad Gateway -
503 Service Unavailable -
504 Gateway Timeout
-
При возобновлении или повторной попытке загрузки запросов используйте стратегию
5xxзадержки . Такие ошибки могут возникать при перегрузке сервера. Экспоненциальная задержка может помочь решить подобные проблемы в периоды большого объема запросов или интенсивного сетевого трафика.Другие типы запросов не следует обрабатывать с экспоненциальной задержкой, но вы все равно можете повторить их несколько раз. При повторных попытках обработки таких запросов ограничьте их количество. Например, ваш код может ограничить количество повторных попыток до десяти или менее, прежде чем будет сообщено об ошибке.
Обработка ошибок
404 Not Foundи410 Goneпри возобновляемой загрузке осуществляется путем начала всей загрузки с самого начала.
Экспоненциальная задержка
Экспоненциальная задержка — это стандартная стратегия обработки ошибок в сетевых приложениях, при которой клиент периодически повторяет неудачный запрос в течение увеличивающегося промежутка времени. Если большой объем запросов или интенсивный сетевой трафик приводят к тому, что сервер возвращает ошибки, экспоненциальная задержка может быть хорошей стратегией для обработки этих ошибок. И наоборот, она не подходит для обработки ошибок, не связанных с объемом сети или временем ответа, таких как недействительные учетные данные авторизации или ошибки «файл не найден».
При правильном использовании экспоненциальная задержка повышает эффективность использования полосы пропускания, сокращает количество запросов, необходимых для получения успешного ответа, и максимизирует пропускную способность запросов в средах с параллельным выполнением.
Процесс реализации простой экспоненциальной задержки выглядит следующим образом:
- Отправьте запрос к API.
- Получен
HTTP 503, указывающий на необходимость повторной отправки запроса. - Подождите 1 секунду + случайное число миллисекунд и повторите запрос.
- Получен
HTTP 503, указывающий на необходимость повторной отправки запроса. - Подождите 2 секунды + случайное число миллисекунд и повторите запрос.
- Получен
HTTP 503, указывающий на необходимость повторной отправки запроса. - Подождите 4 секунды + случайное число миллисекунд и повторите запрос.
- Получен
HTTP 503 response, указывающий на необходимость повторной отправки запроса. - Подождите 8 секунд + случайное число миллисекунд и повторите запрос.
- Получен
HTTP 503 response, указывающий на необходимость повторной отправки запроса. - Подождите 16 секунд + случайное число миллисекунд и повторите запрос.
- Стоп. Сообщите об ошибке или зарегистрируйте её.
В приведенном выше списке random_number_milliseconds — это случайное число миллисекунд, меньшее или равное 1000. Это необходимо, поскольку введение небольшой случайной задержки помогает более равномерно распределить нагрузку и избежать перегрузки сервера. Значение random_number_milliseconds необходимо переопределять после каждого ожидания.
Алгоритм настроен на завершение работы, когда n равно 5. Это ограничение предотвращает бесконечные повторные попытки клиентов и приводит к общей задержке около 32 секунд, прежде чем запрос будет признан «неисправимой ошибкой». Большее максимальное количество повторных попыток допустимо, особенно если выполняется длительная загрузка; просто убедитесь, что задержка повторных попыток ограничена разумным значением, например, менее одной минуты.