Cargar medios

La carga de elementos multimedia es un proceso de dos pasos:

  1. Sube los bytes de tus archivos multimedia a un servidor de Google mediante el extremo de carga. Se mostrará un token de carga que identifica los bytes subidos.
  2. Usa una llamada batchCreate con el token de carga para crear un elemento multimedia en la cuenta de Google Fotos del usuario.

En estos pasos, se describe el proceso de subir un solo elemento multimedia. Si subes varios elementos multimedia (muy probable para cualquier aplicación de producción), revisa las prácticas recomendadas para las cargas a fin de mejorar la eficiencia de la carga.

Antes de comenzar

Alcances de autorización obligatorios

Para subir elementos multimedia a la biblioteca o al álbum de un usuario, se requiere el alcance photoslibrary.appendonly o photoslibrary.

Los elementos multimedia también se pueden crear con el alcance photoslibrary.sharing. Para crear elementos con el alcance photoslibrary.sharing, primero debes crear un álbum y marcarlo como compartido con shareAlbum. Luego, puedes crear elementos multimedia para compartir con el usuario en el álbum. No puedes crear elementos directamente en la biblioteca del usuario ni en álbumes que tu app no haya compartido.

Cuando se enumeran álbumes, la propiedad isWriteable indica si tu aplicación tiene acceso para crear contenido multimedia en un álbum en particular.

Tipos y tamaños de archivo aceptados

Puedes subir los tipos de archivo que se indican en la siguiente tabla.

Tipo de medio Tipos de archivo aceptados Tamaño máximo del archivo
Fotos AVIF, BMP, GIF, HEIC, ICO, JPG, PNG, TIFF, WEBP, algunos archivos RAW 200 MB
Videos 3GP, 3G2, ASF, AVI, DIVX, M2T, M2TS, M4V, MKV, MMV, MOD, MOV, MP4, MPG, MTS, TOD y WMV. 20 GB

Paso 1: Sube bytes

Sube bytes a Google mediante solicitudes de carga. Una solicitud de carga correcta muestra un token de carga en forma de cadena de texto sin procesar. Usa estos tokens de carga para crear elementos multimedia con la llamada batchCreate.

REST

Incluye los siguientes campos en el encabezado de la solicitud POST:

Campos de encabezado
Content-type Debes establecerlo en application/octet-stream.
X-Goog-Upload-Content-Type Recomendado. Se establece en el tipo de MIME de los bytes que subirás. Los tipos de MIME comunes incluyen image/jpeg, image/png y image/gif.
X-Goog-Upload-Protocol Debes establecerlo en raw.

A continuación, se muestra un encabezado de la solicitud 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

En el cuerpo de la solicitud, incluye el objeto binario del archivo:

media-binary-data

Si esta solicitud POST se realiza correctamente, se muestra un token de carga en forma de string de texto sin procesar como cuerpo de la respuesta. Para crear elementos multimedia, usa estas cadenas de texto en la llamada a 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
}

El tamaño de archivo sugerido para las imágenes es inferior a 50 MB. Los archivos de más de 50 MB pueden generar problemas de rendimiento.

La API de la Biblioteca de Google Fotos admite cargas reanudables. Una carga reanudable te permite dividir un archivo multimedia en varias secciones y subir una sección a la vez.

Paso 2: Crea un elemento multimedia

Después de subir los bytes de tus archivos multimedia, puedes crearlos como elementos multimedia en Google Fotos con tokens de carga. Un token de carga es válido durante un día después de su creación. Un elemento multimedia siempre se agrega a la biblioteca del usuario. Solo se pueden agregar elementos multimedia a álbumes creados por tu app. Para obtener más información, consulta Alcances de la autorización.

Para crear nuevos elementos multimedia, llama a mediaItems.batchCreate especificando una lista de newMediaItems. Cada newMediaItem contiene un token de carga que se especifica dentro de un simpleMediaItem y una descripción opcional que se muestra al usuario.

El campo de descripción está restringido a 1,000 caracteres y solo debe incluir texto significativo creado por los usuarios. Por ejemplo, "Nuestro viaje al parque" o "Cena navideña". No incluyas metadatos como nombres de archivos, etiquetas programáticas ni otro texto generado automáticamente.

Si deseas obtener el mejor rendimiento, incluye varios elementos multimedia en una llamada para reducir la cantidad de llamadas a mediaItems.batchCreate que debes realizar. Siempre espera hasta que se complete la solicitud anterior antes de realizar una llamada posterior para el mismo usuario.

Para crear uno o varios elementos multimedia en la biblioteca de un usuario, especifica las descripciones y los tokens de carga correspondientes:

REST

Este es el encabezado de la solicitud POST:

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

El cuerpo de la solicitud debe especificar una 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
}


Para agregar elementos multimedia a la biblioteca y a un álbum, especifica el álbum id. Para obtener más información, consulta Cómo crear álbumes.

Cada álbum puede contener hasta 20,000 elementos multimedia. Las solicitudes para crear elementos multimedia en un álbum que superen este límite fallarán.

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
}

También puedes especificar albumId y albumPosition para insertar elementos multimedia en una ubicación específica del á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 obtener más detalles sobre el posicionamiento en los álbumes, consulta Cómo agregar enriquecimientos.

Respuesta de creación del elemento

La llamada a mediaItems.batchCreate muestra el resultado de cada uno de los elementos multimedia que intentaste crear. La lista de newMediaItemResults indica el estado y, además, incluye el uploadToken de la solicitud. Un código de estado distinto de cero indica un error.

REST

Si todos los elementos multimedia se crearon correctamente, la solicitud muestra el estado HTTP 200 OK. Si no se pueden crear algunos elementos multimedia, la solicitud muestra el estado HTTP 207 MULTI-STATUS para indicar el éxito 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();
        // ...
    }
}

Si un elemento se agrega de forma correcta, se muestra una mediaItem que contiene sus mediaItemId, productUrl y mediaMetadata. Para obtener más información, consulta Cómo acceder a elementos multimedia.

Si el elemento multimedia es un video, primero se debe procesar. El mediaItem contiene un status dentro de su mediaMetadata que describe el estado de procesamiento del archivo de video. Un archivo recién subido muestra el estado PROCESSING primero, antes de que sea READY para su uso. Para obtener más detalles, consulta Cómo acceder a los elementos multimedia.

Si se produce un error durante esta llamada, sigue las prácticas recomendadas y vuelve a enviar la solicitud. Es posible que quieras hacer un seguimiento de las incorporaciones realizadas correctamente, de modo que la imagen se pueda insertar en el álbum en la posición correcta durante la siguiente solicitud. Para obtener más información, consulta Cómo crear álbumes.

Los resultados siempre se muestran en el mismo orden en el que se enviaron los tokens de carga.

Prácticas recomendadas para subir contenido

Los siguientes recursos y prácticas recomendadas te ayudan a mejorar la eficiencia general con las cargas:

  • Usa una de nuestras bibliotecas cliente compatibles.
  • Sigue las prácticas recomendadas de reintento y manejo de errores y ten en cuenta lo siguiente:
    • Los errores 429 pueden ocurrir cuando se agota tu cuota o si tienes una frecuencia limitada por realizar demasiadas llamadas demasiado rápido. Asegúrate de no llamar a batchCreate para el mismo usuario hasta que se haya completado la solicitud anterior.
    • Los errores 429 requieren una demora mínima de 30s antes de volver a intentarlo. Usa una estrategia de retirada exponencial cuando reintentes las solicitudes.
    • Los errores 500 se producen cuando el servidor encuentra un error. Cuando subes datos, lo más probable es que se deba a que realizas varias llamadas de escritura (como batchCreate) para el mismo usuario a la vez. Verifica los detalles de tu solicitud y no realices llamadas a batchCreate en paralelo.
  • Usa el flujo de carga reanudable para que tus cargas sean más sólidas en caso de interrupciones de red, lo que reduce el uso de ancho de banda, ya que te permite reanudar las cargas completadas de forma parcial. Esto es importante cuando subes archivos desde dispositivos móviles de clientes o cuando subes archivos grandes.

Además, ten en cuenta las siguientes sugerencias para cada paso del proceso de carga: subir bytes y, luego, crear elementos multimedia.

Subiendo bytes

Cómo crear elementos multimedia

  • No realices llamadas en paralelo a batchCreate para un solo usuario.

    • Para cada usuario, realiza llamadas a batchCreate una tras otra (en serie).
    • En el caso de varios usuarios, siempre realiza llamadas de batchCreate para cada usuario uno tras otro. Solo realiza llamadas para diferentes usuarios en paralelo.
  • Incluye tantas NewMediaItems como sea posible en cada llamada a batchCreate para minimizar la cantidad total de llamadas que debes hacer. Puedes incluir 50 elementos como máximo.

  • Establece un texto de descripción significativo que hayan creado los usuarios. No incluyas metadatos como nombres de archivos, etiquetas programáticas ni otro texto generado automáticamente en el campo de descripción.

Explicación de ejemplo

En este ejemplo, se usa pseudocódigo a fin de explicar cómo subir elementos multimedia para varios usuarios. El objetivo es describir ambos pasos del proceso de carga (subir bytes sin procesar y crear elementos multimedia) y detallar las prácticas recomendadas para compilar una integración de carga eficiente y resiliente.

Paso 1: Sube bytes sin procesar

Primero, crea una cola con el fin de subir los bytes sin procesar de todos los usuarios para tus elementos multimedia. Realiza un seguimiento de cada uno de los uploadToken que se muestran por usuario. Recuerda estos puntos clave:

  • La cantidad de subprocesos de carga simultáneos depende de tu entorno operativo.
  • Considera reordenar la cola de carga según sea necesario. Por ejemplo, puedes priorizar las cargas en función de la cantidad de cargas restantes por usuario, el progreso general de un usuario y otros 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

Paso 2: Crea elementos multimedia

En el paso 1, puedes subir varios bytes de varios usuarios en paralelo, pero, en el paso 2, solo puedes realizar una llamada para cada usuario a la 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.

Continúa con este proceso hasta que se completen todas las cargas y llamadas de creación de contenido multimedia.