Fazer upload de mídia

O upload de itens de mídia é um processo de duas etapas:

  1. Faça upload dos bytes dos arquivos de mídia para um servidor do Google usando o endpoint de uploads. Isso retorna um token de upload que identifica os bytes enviados.
  2. Use uma chamada de batchCreate com o token de upload para criar um item de mídia na conta do Google Fotos do usuário.

Estas etapas descrevem o processo de upload de um único item de mídia. Se você for fazer upload de diversos itens de mídia (provavelmente para qualquer aplicativo de produção), leia as práticas recomendadas de envios para melhorar seu de envios mais eficientes.

Antes de começar

Escopos de autorização necessários

O upload de itens de mídia para a biblioteca ou o álbum de um usuário exige o photoslibrary.appendonly ou o escopo photoslibrary.

Itens de mídia também podem ser criados usando o escopo photoslibrary.sharing. Para criar itens com o escopo photoslibrary.sharing, primeiro é necessário criar um álbum e marque-o como compartilhado usando shareAlbum. Depois disso, é possível criar itens de mídia compartilhados com o usuário no álbum. Não é possível criar itens diretamente no na biblioteca do usuário ou em álbuns que não foram compartilhados pelo app.

Ao listar álbuns, a propriedade isWriteable indica se suas tem acesso para criar mídia em um álbum específico.

Tipos e tamanhos de arquivos aceitos

Você pode fazer o upload dos tipos de arquivo listados na tabela abaixo.

Tipo de mídia Tipos de arquivos aceitos Tamanho máximo do arquivo
Fotos AVIF, BMP, GIF, HEIC, ICO, JPG, PNG, TIFF, WEBP e alguns arquivos RAW. 200 MB
Vídeos 3GP, 3G2, ASF, AVI, DIVX, M2T, M2TS, M4V, MKV, MMV, MOD, MOV, MP4 MPG, MTS, TOD e WMV. 20 GB

Etapa 1: fazer upload de bytes

Fazer upload de bytes para o Google usando solicitações de upload. Uma solicitação de upload foi concluída retorna um token de upload na forma de uma string de texto bruto. Usar estes uploads para criar itens de mídia com a chamada batchCreate.

REST

Inclua os seguintes campos no cabeçalho da solicitação POST:

Campos de cabeçalho
Content-type Defina como application/octet-stream.
X-Goog-Upload-Content-Type Recomendado. Defina de acordo com o tipo MIME dos bytes que estão sendo enviados. Tipos MIME comuns incluem image/jpeg, image/png e image/gif.
X-Goog-Upload-Protocol Defina como raw.

Aqui está um cabeçalho de solicitação 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

No corpo da solicitação, inclua o binário do arquivo:

media-binary-data

Se essa solicitação POST for bem-sucedida, um token de upload que está no formato de uma string de texto bruto, é retornado como o corpo da resposta. Para criar mídia itens, use essas strings de texto na chamada de batchCreate.

upload-token

Java

// 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
}

O tamanho de arquivo sugerido para imagens é inferior a 50 MB. Arquivos com mais de 50 MB são suscetíveis a problemas de desempenho.

A API Google Photos Library é compatível uploads retomáveis. Um O upload permite dividir um arquivo de mídia em várias seções e fazer upload de uma seção por vez.

Etapa 2: criar um item de mídia

Depois de fazer upload dos bytes dos arquivos de mídia, é possível criá-los como arquivos de mídia itens do Google Fotos usando tokens de upload. Um token de upload é válido por um dia após a criação. Um item de mídia é sempre adicionado ao biblioteca. Itens de mídia só podem ser adicionados aos álbuns criados pelo seu app. Para mais informações, consulte Escopos de autorização.

Para criar novos itens de mídia, chame mediaItems.batchCreate especificando uma lista de newMediaItems. Cada newMediaItem contém um upload token especificado em simpleMediaItem, e uma descrição opcional que é mostrado ao usuário.

O campo de descrição pode ter no máximo 1.000 caracteres e deve incluir texto significativo criado pelos usuários. Por exemplo, "Nossa viagem ao parque". ou "Jantar de Natal". Não inclua metadados, como nomes de arquivos, nem metadados tags ou outros textos gerados automaticamente.

Para ter o melhor desempenho, reduza o número de chamadas para mediaItems.batchCreate incluindo vários itens de mídia em uma chamada. Sempre aguardar até que a solicitação anterior seja concluída antes de fazer uma chamada subsequente para o ao mesmo usuário.

Você pode criar um ou vários itens de mídia na biblioteca de um usuário especificando as descrições e os tokens de upload correspondentes:

REST

Este é o cabeçalho da solicitação POST:

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

O corpo da solicitação precisa especificar uma lista de newMediaItems.

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

Java

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
}

Você pode adicionar itens de mídia à biblioteca e a um álbum especificando o álbum id. Para mais informações, consulte Crie álbuns.

Cada álbum pode conter até 20.000 itens de mídia. Solicitações para criar mídia os itens de um álbum que excederem esse limite falharão.

REST

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

Java

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
}

Também é possível especificar albumId e albumPosition para inserir itens de mídia em um local específico no álbum.

REST

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

Java

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
}

Para mais detalhes sobre o posicionamento nos álbuns, consulte Adicionar melhorias.

Resposta de criação de item

A chamada mediaItems.batchCreate retorna o resultado de cada um dos itens de mídia. que você tentou criar. A lista de newMediaItemResults indica o status e inclui o uploadToken da solicitação. Um código de status diferente de zero indica erro.

REST

Se todos os itens de mídia tiverem sido criados corretamente, a solicitação retornará Status HTTP 200 OK. Se não for possível criar alguns itens de mídia, a solicitação retorna o status HTTP 207 MULTI-STATUS para indicar sucesso parcial.

{
  "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"
      }
    }
  ]
}

Java

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();
        // ...
    }
}

Se um item for adicionado, será retornado mediaItem contendo o mediaItemId, productUrl e mediaMetadata. Para mais informações, consulte Acessar itens de mídia

Se o item de mídia for um vídeo, ele terá que ser processado primeiro. O mediaItem contém um status dentro da mediaMetadata que descreve o processamento do arquivo de vídeo. Um arquivo recém-enviado retorna o status PROCESSING primeiro, antes de ser READY para uso. Para mais detalhes, consulte Acessar itens de mídia

Se você encontrar um erro durante a chamada, siga as Práticas recomendadas e faça a solicitação novamente. Você pode querer acompanhar as adições bem-sucedidas, para que a imagem possa ser inserida para o álbum na posição correta durante a próxima solicitação. Para mais informações, consulte Crie álbuns.

Os resultados são sempre retornados na mesma ordem em que os tokens de upload foram enviados.

Práticas recomendadas para envios

As práticas recomendadas e os recursos a seguir ajudam a melhorar sua eficiência geral com uploads:

  • Use uma de nossas bibliotecas de cliente compatíveis.
  • Siga as práticas recomendadas de nova tentativa e tratamento de erros. lembrando do seguinte:
    • 429 erros podem ocorrer quando sua cota acaba ou você tem uma taxa limitada por fazer muitas chamadas rápido demais. Confirme se não chame batchCreate para o mesmo usuário até que a solicitação for concluída.
    • Os erros 429 exigem um atraso mínimo de 30s antes de tentar novamente. Use um espera exponencial de registros ao repetir solicitações.
    • Os erros 500 ocorrem quando o servidor encontra um erro. Ao fazer o upload, Isso se deve provavelmente ao fato de haver várias chamadas de gravação (como batchCreate) para o mesmo usuário ao mesmo tempo. Confira os detalhes sua solicitação e não faça chamadas para batchCreate em paralelo.
  • Use o fluxo de upload retomável para tornar seus uploads mais robustos em caso de interrupções de rede, reduzindo uso de largura de banda, permitindo que você retome uploads parcialmente concluídos. Isso é importante ao enviar de dispositivos móveis clientes ou ao fazer o upload de arquivos grandes.

Considere também as seguintes dicas para cada etapa do processo de envio: fazer upload de bytes e, em seguida, criar itens de mídia.

Fazendo upload de bytes

  • O upload de bytes (para recuperar tokens de upload) pode ser feito em paralelo.
  • Sempre defina o tipo MIME correto no cabeçalho X-Goog-Upload-Content-Type. para cada chamada de upload.

Como criar itens de mídia

  • Não faça chamadas em paralelo com batchCreate para um único usuário.

    • Para cada usuário, faça chamadas para batchCreate uma após a outra (em serial).
    • Para vários usuários, sempre faça chamadas batchCreate para cada um deles. depois da outra. Faça chamadas apenas para diferentes usuários em paralelo.
  • Inclua o máximo de NewMediaItems possível em cada chamada para batchCreate para minimizar o número total de chamadas que você tem fazer. Você pode incluir no máximo 50 itens.

  • Defina um texto de descrição significativo. que foi criado pelos usuários. Não inclua metadados como nomes de arquivos, tags programáticas ou outros textos gerados automaticamente na descrição.

Exemplo de tutorial

Este exemplo usa pseudocódigo para orientar o upload de itens de mídia para vários usuários. O objetivo é delinear as duas etapas do processo de envio (fazer o upload de imagens bytes e como criar itens de mídia) e detalhar as práticas recomendadas para criar um upload eficiente e resiliente integração total.

Etapa 1: fazer o upload de bytes brutos

Primeiro, crie uma fila para fazer upload dos bytes brutos para seus itens de mídia de todos os seus usuários. Acompanhe cada uploadToken retornado por usuário. Lembre-se destes pontos-chave:

  • O número de threads de upload simultâneo depende do sistema operacional de nuvem.
  • Considere reordenar a fila de upload conforme necessário. Por exemplo, é possível priorize os uploads com base no número de uploads restantes por usuário, uma progresso geral do usuário ou outros requisitos.

Pseudocódigo

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

Etapa 2: criar itens de mídia

Na etapa 1, é possível fazer o upload de vários bytes de vários usuários em paralelo, mas Na etapa 2, você só pode fazer uma chamada para cada usuário de cada vez.

Pseudocódigo

// 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.

Continue esse processo até que todos os uploads e chamadas de criação de mídia sejam concluídos.