Как загрузить медиа

Загрузка медиа-элементов представляет собой двухэтапный процесс:

  1. Загрузите байты своих медиафайлов на сервер Google, используя конечную точку загрузки . Это возвращает токен загрузки, который идентифицирует загруженные байты.
  2. Используйте вызов BatchCreate с токеном загрузки, чтобы создать элемент мультимедиа в учетной записи Google Фото пользователя.

Эти шаги описывают процесс загрузки одного медиа-элемента. Если вы загружаете несколько медиа-элементов (что вполне вероятно для любого производственного приложения), ознакомьтесь с рекомендациями по загрузке, чтобы повысить эффективность загрузки.

Прежде чем вы начнете

Требуемые области авторизации

Для загрузки элементов мультимедиа в библиотеку или альбом пользователя требуется либо photoslibrary.appendonly , либо область photoslibrary .

Медиа-элементы также можно создавать с использованием области photoslibrary.sharing . Чтобы создать элементы с областью photoslibrary.sharing , необходимо сначала создать альбом и пометить его как общий с помощью shareAlbum . Затем вы можете создавать в альбоме элементы мультимедиа, к которым будет предоставлен общий доступ пользователю. Вы не можете создавать элементы непосредственно в библиотеке пользователя или в альбомах, к которым ваше приложение не предоставило общий доступ.

При перечислении альбомов свойство isWriteable указывает, имеет ли ваше приложение доступ для создания мультимедиа в определенном альбоме.

Допустимые типы и размеры файлов

Вы можете загрузить типы файлов, перечисленные в таблице ниже.

Тип носителя Допустимые типы файлов Максимальный размер файла
Фото AVIF, BMP, GIF, HEIC, ICO, JPG, PNG, TIFF, WEBP, некоторые файлы RAW. 200 МБ
Видео 3GP, 3G2, ASF, AVI, DIVX, M2T, M2TS, M4V, MKV, MMV, MOD, MOV, MP4, MPG, MTS, TOD, WMV. 20 ГБ

Шаг 1. Загрузка байтов

Загрузите байты в Google, используя запросы на загрузку. Успешный запрос на загрузку возвращает токен загрузки в виде необработанной текстовой строки. Используйте эти токены загрузки для создания элементов мультимедиа с помощью вызова batchCreate .

ОТДЫХ

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

Поля заголовка
Content-type Установите значение application/octet-stream .
X-Goog-Upload-Content-Type Рекомендуемые. Установите тип MIME загружаемых байтов. Общие типы MIME включают image/jpeg , image/png и image/gif .
X-Goog-Upload-Protocol Установите raw .

Вот заголовок POST-запроса:

POST https://photoslibrary.googleapis.com/v1/uploads
Authorization: Bearer oauth2-token
Content-type: application/octet-stream
X-Goog-Upload-Content-Type: mime-type
X-Goog-Upload-Protocol: raw

В тело запроса включите двоичный файл файла:

media-binary-data

Если этот запрос POST успешен, токен загрузки в виде необработанной текстовой строки возвращается в качестве тела ответа. Чтобы создать элементы мультимедиа, используйте эти текстовые строки в вызове batchCreate .

upload-token

Джава

// Open the file and automatically close it after upload
try (RandomAccessFile file = new RandomAccessFile(pathToFile, "r")) {
  // Create a new upload request
  UploadMediaItemRequest uploadRequest =
      UploadMediaItemRequest.newBuilder()
              // The media type (e.g. "image/png")
              .setMimeType(mimeType)
              // The file to upload
              .setDataFile(file)
          .build();
  // Upload and capture the response
  UploadMediaItemResponse uploadResponse = photosLibraryClient.uploadMediaItem(uploadRequest);
  if (uploadResponse.getError().isPresent()) {
    // If the upload results in an error, handle it
    Error error = uploadResponse.getError().get();
  } else {
    // If the upload is successful, get the uploadToken
    String uploadToken = uploadResponse.getUploadToken().get();
    // Use this upload token to create a media item
  }
} catch (ApiException e) {
  // Handle error
} catch (IOException e) {
  // Error accessing the local file
}

PHP

try {
    // Create a new upload request by opening the file
    // and specifying the media type (e.g. "image/png")
    $uploadToken = $photosLibraryClient->upload(file_get_contents($localFilePath), null, $mimeType);
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
    // Handle error
}

Рекомендуемый размер файла изображений — менее 50 МБ. Файлы размером более 50 МБ подвержены проблемам с производительностью.

API библиотеки Google Фото поддерживает возобновляемую загрузку . Возобновляемая загрузка позволяет разделить медиафайл на несколько разделов и загружать по одному разделу за раз.

Шаг 2. Создание медиа-элемента

После загрузки байтов ваших медиафайлов вы можете создать их как медиаэлементы в Google Фото, используя токены загрузки. Токен загрузки действителен в течение одного дня после создания. Медиа-элемент всегда добавляется в библиотеку пользователя. Медиа-элементы можно добавлять только в альбомы, созданные вашим приложением. Дополнительные сведения см. в разделе Области авторизации .

Чтобы создать новые элементы мультимедиа, вызовите mediaItems.batchCreate , указав список newMediaItems . Каждый newMediaItem содержит токен загрузки, указанный внутри simpleMediaItem , и необязательное описание, которое отображается пользователю.

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

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

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

ОТДЫХ

Вот заголовок POST-запроса:

POST https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate
Content-type: application/json
Authorization: Bearer oauth2-token

В теле запроса должен быть указан список newMediaItems .

{
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
   , ...
  ]
}

Джава

try {
  // Create a NewMediaItem with the following components:
  // - uploadToken obtained from the previous upload request
  // - filename that will be shown to the user in Google Photos
  // - description that will be shown to the user in Google Photos
  NewMediaItem newMediaItem = NewMediaItemFactory
          .createNewMediaItem(uploadToken, fileName, itemDescription);
  List<NewMediaItem> newItems = Arrays.asList(newMediaItem);

  BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems);
  for (NewMediaItemResult itemsResponse : response.getNewMediaItemResultsList()) {
    Status status = itemsResponse.getStatus();
    if (status.getCode() == Code.OK_VALUE) {
      // The item is successfully created in the user's library
      MediaItem createdItem = itemsResponse.getMediaItem();
    } else {
      // The item could not be created. Check the status and try again
    }
  }
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $newMediaItems = [];
    // Create a NewMediaItem with the following components:
    // - uploadToken obtained from the previous upload request
    // - filename that will be shown to the user in Google Photos
    // - description that will be shown to the user in Google Photos
    $newMediaItems[0] = PhotosLibraryResourceFactory::newMediaItemWithDescriptionAndFileName(
            $uploadToken, $itemDescription, $fileName);

    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems);
    foreach ($response->getNewMediaItemResults() as $itemResult) {
        $status = $itemResult->getStatus();
        if ($status->getCode() != Code::OK) {
            // Error while creating the item.
        }
    }
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}


Вы можете добавлять мультимедийные элементы в библиотеку и в альбом, указав id альбома. Дополнительную информацию см. в разделе Создание альбомов .

Каждый альбом может содержать до 20 000 медиа-элементов. Запросы на создание медиа-элементов в альбоме, превышающие этот предел, не будут выполнены.

ОТДЫХ

{
  "albumId": "album-id",
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
   , ...
  ]
}

Джава

try {
  // Create new media items in a specific album
  BatchCreateMediaItemsResponse response = photosLibraryClient
      .batchCreateMediaItems(albumId, newItems);
  // Check the response
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems, ['albumId' => $albumId]);
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}

Вы также можете указать albumId и albumPosition , чтобы вставлять элементы мультимедиа в определенное место в альбоме.

ОТДЫХ

{
  "albumId": "album-id",
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
    , ...
  ],
  "albumPosition": {
    "position": "after-media-item",
    "relativeMediaItemId": "media-item-id"
  }
}

Джава

try {
  // Create new media items in a specific album, positioned after a media item
  AlbumPosition positionInAlbum = AlbumPositionFactory.createFirstInAlbum();
  BatchCreateMediaItemsResponse response = photosLibraryClient
      .batchCreateMediaItems(albumId, newItems, positionInAlbum);
  // Check the response
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $albumPosition = PhotosLibraryResourceFactory::albumPositionAfterMediaItem($mediaItemId);
    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems,
        ['albumId' => $albumId, 'albumPosition' => $albumPosition]);
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}

Дополнительные сведения о расположении в альбомах см. в разделе Добавление дополнений .

Ответ на создание элемента

Вызов mediaItems.batchCreate возвращает результат для каждого из элементов мультимедиа, которые вы пытались создать. Список newMediaItemResults указывает состояние и включает в себя uploadToken для запроса. Ненулевой код состояния указывает на ошибку.

ОТДЫХ

Если все медиа-элементы были успешно созданы, запрос возвращает статус HTTP 200 OK . Если некоторые элементы мультимедиа не могут быть созданы, запрос возвращает статус HTTP 207 MULTI-STATUS указывающий на частичный успех.

{
  "newMediaItemResults": [
    {
      "uploadToken": "upload-token",
      "status": {
        "message": "Success"
      },
      "mediaItem": {
        "id": "media-item-id",
        "description": "item-description",
        "productUrl": "https://photos.google.com/photo/photo-path",
        "mimeType": "mime-type",
        "mediaMetadata": {
          "width": "media-width-in-px",
          "height": "media-height-in-px",
          "creationTime": "creation-time",
          "photo": {}
        },
        "filename": "filename"
      }
    },
    {
      "uploadToken": "upload-token",
      "status": {
        "code": 13,
        "message": "Internal error"
      }
    }
  ]
}

Джава

BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems);

// The response contains a list of NewMediaItemResults
for (NewMediaItemResult result : response.getNewMediaItemResultsList()) {
  // Each result item is identified by its uploadToken
  String uploadToken = result.getUploadToken();
  Status status = result.getStatus();

  if (status.getCode() == Code.OK_VALUE) {
    // If the request is successful, a MediaItem is returned
    MediaItem mediaItem = result.getMediaItem();
    String id = mediaItem.getId();
    String productUrl = mediaItem.getProductUrl();
    // ...
  }
}

PHP

// The response from a call to batchCreateMediaItems returns a list of NewMediaItemResults
foreach ($response->getNewMediaItemResults() as $itemResult) {
    // Each result item is identified by its uploadToken
    $itemUploadToken = $itemResult->getUploadToken();
    // Verify the status of each entry to ensure that the item has been uploaded correctly
    $itemStatus = $itemResult->getStatus();
    if ($itemStatus->getCode() != Code::OK) {
        // Error when item is being created
    } else {
        // Media item is successfully created
        // Get the MediaItem object from the response
        $mediaItem = $itemResult->getMediaItem();
        // It contains details such as the Id of the item, productUrl
        $id = $mediaItem->getId();
        $productUrl = $mediaItem->getProductUrl();
        // ...
    }
}

Если элемент успешно добавлен, возвращается объект mediaItem , содержащий его mediaItemId , productUrl и mediaMetadata . Дополнительные сведения см. в разделе Доступ к элементам мультимедиа .

Если медиа-элементом является видео, его необходимо обработать в первую очередь. mediaItem содержит status внутри своих mediaMetadata , который описывает состояние обработки видеофайла. Недавно загруженный файл сначала возвращает статус PROCESSING , а затем READY к использованию. Подробную информацию см. в разделе Доступ к элементам мультимедиа .

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

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

Рекомендации по загрузке

Следующие рекомендации и ресурсы помогут повысить общую эффективность загрузки:

  • Используйте одну из наших поддерживаемых клиентских библиотек .
  • Следуйте рекомендациям по повторным попыткам и обработке ошибок , учитывая следующие моменты:
    • Ошибки 429 могут возникнуть, когда ваша квота исчерпана или вы ограничены в скорости из-за слишком большого количества вызовов слишком быстро. Убедитесь, что вы не вызываете batchCreate для того же пользователя до тех пор, пока не завершится предыдущий запрос.
    • При возникновении ошибок 429 требуется задержка минимум 30s перед повторной попыткой. Используйте экспоненциальную стратегию отсрочки при повторных запросах.
    • Ошибки 500 возникают, когда сервер обнаруживает ошибку. При загрузке это, скорее всего, происходит из-за одновременного выполнения нескольких вызовов записи (например, batchCreate ) для одного и того же пользователя. Проверьте детали вашего запроса и не делайте параллельные вызовы batchCreate .
  • Используйте возобновляемый поток загрузки, чтобы сделать загрузку более надежной в случае сбоев в сети, сокращая использование полосы пропускания и позволяя возобновить частично завершенную загрузку. Это важно при загрузке с клиентских мобильных устройств или при загрузке больших файлов.

Также примите во внимание следующие советы для каждого этапа процесса загрузки: загрузка байтов и последующее создание элементов мультимедиа .

Загрузка байтов

  • Загрузка байтов (для получения токенов загрузки) может выполняться параллельно.
  • Всегда устанавливайте правильный тип MIME в заголовке X-Goog-Upload-Content-Type для каждого вызова загрузки.

Создание медиа-элементов

  • Не делайте вызовы параллельно с batchCreate для одного пользователя.

    • Для каждого пользователя выполните вызовы batchCreate один за другим (последовательно).
    • Для нескольких пользователей всегда выполняйте вызовы batchCreate для каждого пользователя один за другим. Звоните только разным пользователям одновременно.
  • Включите как можно больше NewMediaItems в каждый вызов batchCreate чтобы свести к минимуму общее количество вызовов, которые вам придется сделать. Максимум вы можете включить 50 элементов.

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

Пример прохождения

В этом примере псевдокод используется для загрузки мультимедийных элементов для нескольких пользователей. Цель — описать оба этапа процесса загрузки ( загрузка необработанных байтов и создание медиа-элементов ) и подробно описать лучшие практики для создания эффективной и отказоустойчивой интеграции загрузки.

Шаг 1. Загрузите необработанные байты

Сначала создайте очередь для загрузки необработанных байтов для ваших медиа-элементов от всех ваших пользователей. Отслеживайте каждый возвращенный uploadToken для каждого пользователя. Помните эти ключевые моменты:

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

Псевдокод

CREATE uploadQueue FROM users, filesToUpload
// Upload media bytes in parallel.
START multiple THREADS
  WHILE uploadQueue is not empty
    POP uploadQueue
    UPLOAD file for user
    GET uploadToken
    CHECK and HANDLE errors
    STORE uploadToken for user in uploadTokensQueue
  END

Шаг 2. Создайте медиа-элементы

На шаге 1 вы можете одновременно загружать несколько байтов от нескольких пользователей, но на шаге 2 вы можете одновременно выполнять только один вызов для каждого пользователя.

Псевдокод

// For each user, create media items once 50 upload tokens have been
// saved, or no more uploads are left per user.
WHEN uploadTokensQueue for user is >= 50 OR no more pending uploads for user
  // Calls can be made in parallel for different users,
  // but only make a single call per user at a time.
  START new thread for (this) user if there is no thread yet
    POP 50 uploadTokens from uploadTokensQueue for user
    CALL mediaItems.batchCreate with uploadTokens
    WAIT UNTIL batchCreate call has completed
    CHECK and HANDLE errors (retry as needed)
  DONE.

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