Subidas de API

La función de subida de contenido multimedia permite que la API BigQuery almacene datos en la nube y los ponga a disposición del servidor. Entre los tipos de datos que se pueden subir se incluyen fotos, vídeos, archivos PDF, archivos ZIP o cualquier otro tipo de datos.

Opciones de subida

La API de BigQuery te permite subir determinados tipos de datos binarios o contenido multimedia. Las características específicas de los datos que puedes subir se especifican en la página de referencia de cualquier método que admita subidas de contenido multimedia:

  • Tamaño máximo de archivo de subida: la cantidad máxima de datos que puedes almacenar con este método.
  • Tipos MIME de contenido multimedia aceptados: los tipos de datos binarios que puedes almacenar con este método.

Puede enviar solicitudes de subida de cualquiera de las siguientes formas. Especifica el método que estás usando con el parámetro de solicitud uploadType.

  • Subida multiparte: uploadType=multipart. Para transferir rápidamente archivos más pequeños y metadatos. Transfiere el archivo junto con los metadatos que lo describen, todo en una sola solicitud.
  • Subida reanudable: uploadType=resumable. Para que la transferencia sea fiable, lo cual es especialmente importante en el caso de archivos de mayor tamaño. Con este método, se usa una solicitud de inicio de sesión que puede incluir metadatos de forma opcional. Esta es una buena estrategia para la mayoría de las aplicaciones, ya que también funciona con archivos más pequeños a cambio de una solicitud HTTP adicional por cada subida.

Cuando subes contenido multimedia, usas un URI especial. De hecho, los métodos que admiten la subida de contenido multimedia tienen dos endpoints URI:

  • El URI /upload del contenido multimedia. El formato del endpoint de subida es el URI de recurso estándar con el prefijo "/upload". Usa este URI cuando transfieras los datos multimedia.

    Ejemplo: POST /upload/bigquery/v2/projects/projectId/jobs

  • El URI de recurso estándar de los metadatos. Si el recurso contiene algún campo de datos, esos campos se usan para almacenar metadatos que describen el archivo subido. Puede usar este URI al crear o actualizar valores de metadatos.

    Ejemplo: POST /bigquery/v2/projects/projectId/jobs

Subida multiparte

Si tiene metadatos que quiere enviar junto con los datos que va a subir, puede hacer una sola solicitud multipart/related. Esta opción es adecuada si los datos que envías son lo suficientemente pequeños como para volver a subirlos por completo si falla la conexión.

Para usar la subida multiparte, haz una solicitud POST al URI /upload del método y añade el parámetro de consulta uploadType=multipart. Por ejemplo:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=multipart

Los encabezados HTTP de nivel superior que se deben usar al hacer una solicitud de subida multiparte son los siguientes:

  • Content-Type. Asigna el valor multipart/related e incluye la cadena de límite que estés usando para identificar las partes de la solicitud.
  • Content-Length. Se asigna al número total de bytes del cuerpo de la solicitud. La parte multimedia de la solicitud debe ser inferior al tamaño máximo de archivo especificado para este método.

El cuerpo de la solicitud tiene el formato de un tipo de contenido multipart/related [RFC2387] y contiene exactamente dos partes. Las partes se identifican mediante una cadena de límite y la cadena de límite final va seguida de dos guiones.

Cada parte de la solicitud multipartita necesita un encabezado Content-Type adicional:

  1. Parte de metadatos: debe aparecer en primer lugar y Content-Type debe coincidir con uno de los formatos de metadatos aceptados.
  2. Parte multimedia: debe ser la segunda y Content-Type debe coincidir con uno de los tipos de MIME multimedia aceptados del método.

Consulta la referencia de la API para ver la lista de tipos MIME de medios admitidos y los límites de tamaño de los archivos subidos de cada método.

Nota: Para crear o actualizar solo la parte de los metadatos, sin subir los datos asociados, simplemente envía una solicitud POST o PUT al endpoint de recurso estándar: https://www.googleapis.com/bigquery/v2/projects/projectId/jobs

Ejemplo: Subida multiparte

En el ejemplo siguiente se muestra una solicitud de subida multiparte para la API BigQuery.

POST /upload/bigquery/v2/projects/projectId/jobs?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

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}


--foo_bar_baz
Content-Type: */*

CSV, JSON, AVRO, PARQUET, or ORC data
--foo_bar_baz--

Si la solicitud se realiza correctamente, el servidor devuelve el código de estado HTTP 200 OK junto con los metadatos:

HTTP/1.1 200
Content-Type: application/json

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

Subida reanudable

Para subir archivos de datos de forma más fiable, puedes usar el protocolo de subida reanudable. Este protocolo te permite reanudar una operación de subida después de que un error de comunicación haya interrumpido el flujo de datos. Es especialmente útil si transfieres archivos grandes y es probable que se produzca una interrupción de la red u otro error de transmisión (por ejemplo, al subir archivos desde una aplicación cliente móvil). También puede reducir el uso del ancho de banda en caso de que se produzcan errores en la red, ya que no tendrás que volver a subir archivos grandes desde el principio.

Para usar la subida reanudable, sigue estos pasos:

  1. Inicia una sesión reanudable. Haz una solicitud inicial al URI de subida que incluya los metadatos, si los hay.
  2. Guarda el URI de la sesión reanudable. Guarda el URI de sesión devuelto en la respuesta de la solicitud inicial. Lo usarás en las solicitudes restantes de esta sesión.
  3. Sube el archivo. Envía el archivo multimedia al URI de la sesión reanudable.

Además, las aplicaciones que usan la subida reanudable deben tener código para reanudar una subida interrumpida. Si se interrumpe una subida, averigua cuántos datos se han recibido correctamente y, a continuación, reanuda la subida desde ese punto.

Nota: Los URIs de subida caducan al cabo de una semana.

Paso 1: Inicia una sesión reanudable

Para iniciar una subida reanudable, haz una solicitud POST al URI /upload del método y añade el parámetro de consulta uploadType=resumable. Por ejemplo:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable

En esta solicitud inicial, el cuerpo está vacío o solo contiene los metadatos. El contenido real del archivo que quieras subir se transferirá en solicitudes posteriores.

Usa los siguientes encabezados HTTP con la solicitud inicial:

  • X-Upload-Content-Type. Se asigna al tipo MIME del contenido multimedia de los datos de subida que se transferirán en solicitudes posteriores.
  • X-Upload-Content-Length. Se define como el número de bytes de datos de subida que se transferirán en solicitudes posteriores.  Si no se conoce la longitud en el momento de enviar esta solicitud, puede omitir este encabezado.
  • Si proporcionas metadatos: Content-Type. Se define según el tipo de datos de los metadatos.
  • Content-Length. Se establece en el número de bytes proporcionado en el cuerpo de esta solicitud inicial. No es obligatorio si usas la codificación de transferencia fragmentada.

Consulta la referencia de la API para ver la lista de tipos MIME de medios admitidos y los límites de tamaño de los archivos subidos de cada método.

Ejemplo: Solicitud de inicio de sesión reanudable

En el ejemplo siguiente se muestra cómo iniciar una sesión reanudable para la API de BigQuery.

POST /upload/bigquery/v2/projects/projectId/jobs?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: */*
X-Upload-Content-Length: 2000000

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

Nota: Para enviar una solicitud inicial de actualización reanudable sin metadatos, deja vacío el cuerpo de la solicitud y asigna el valor 0 al encabezado Content-Length.

En la siguiente sección se describe cómo gestionar la respuesta.

Paso 2: Guarda el URI de la sesión reanudable

Si la solicitud de inicio de sesión se realiza correctamente, el servidor de la API responde con un código de estado HTTP 200 OK. Además, proporciona un encabezado Location que especifica el URI de la sesión reanudable. El encabezado Location, que se muestra en el ejemplo de abajo, incluye una parte del parámetro de consulta upload_id que proporciona el ID de subida único que se debe usar en esta sesión.

Ejemplo: Respuesta de inicio de sesión reanudable

Esta es la respuesta a la solicitud del paso 1:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

El valor del encabezado Location, tal como se muestra en la respuesta de ejemplo anterior, es el URI de sesión que usarás como endpoint HTTP para subir el archivo o consultar el estado de la subida.

Copia y guarda el URI de sesión para poder usarlo en solicitudes posteriores.

Paso 3: Sube el archivo

Para subir el archivo, envía una solicitud PUT al URI de subida que has obtenido en el paso anterior. El formato de la solicitud de subida es el siguiente:

PUT session_uri

Los encabezados HTTP que se deben usar al hacer las solicitudes de subida de archivos reanudables incluyen Content-Length. Asigna a este campo el número de bytes que vas a subir en esta solicitud, que suele ser el tamaño del archivo que se va a subir.

Ejemplo: Solicitud de subida de archivos reanudable

A continuación, se muestra una solicitud reanudable para subir el archivo CSV, JSON, AVRO, PARQUET u ORC de 2.000.000 bytes completo del ejemplo actual.

PUT https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: */*

bytes 0-1999999

Si la solicitud se realiza correctamente, el servidor responde con un HTTP 201 Created, junto con los metadatos asociados a este recurso. Si la solicitud inicial de la sesión reanudable hubiera sido un PUT para actualizar un recurso, la respuesta correcta sería 200 OK, junto con los metadatos asociados a este recurso.

Si se interrumpe la solicitud de subida o recibes una respuesta HTTP 503 Service Unavailable o cualquier otra respuesta 5xx del servidor, sigue el procedimiento descrito en Reanudar una subida interrumpida.  


Subir el archivo en fragmentos

Con las subidas reanudables, puedes dividir un archivo en fragmentos y enviar una serie de solicitudes para subir cada fragmento en secuencia. No es el método recomendado, ya que las solicitudes adicionales conllevan costes de rendimiento y, por lo general, no son necesarias. Sin embargo, es posible que tengas que usar la fragmentación para reducir la cantidad de datos transferidos en una sola solicitud. Esto resulta útil cuando hay un límite de tiempo fijo para las solicitudes individuales, como ocurre con determinadas clases de solicitudes de Google App Engine. También te permite hacer cosas como proporcionar indicaciones de progreso de subida para navegadores antiguos que no admiten el progreso de subida de forma predeterminada.


Reanudar una subida interrumpida

Si una solicitud de subida se termina antes de recibir una respuesta o si recibes una respuesta HTTP 503 Service Unavailable del servidor, debes reanudar la subida interrumpida. Para hacer esto:

  1. Estado de la solicitud. Consulta el estado actual de la subida enviando una solicitud PUT vacía al URI de subida. En esta solicitud, los encabezados HTTP deben incluir un encabezado Content-Range que indique que se desconoce la posición actual en el archivo.  Por ejemplo, defina Content-Range como */2000000 si la longitud total del archivo es de 2.000.000. Si no sabes el tamaño completo del archivo, asigna el valor Content-Range a */*.

    Nota: Puedes solicitar el estado entre fragmentos, no solo si se interrumpe la subida. Esto resulta útil, por ejemplo, si quieres mostrar indicaciones del progreso de la subida en navegadores antiguos.

  2. Obtener el número de bytes subidos. Procesa la respuesta de la consulta de estado. El servidor usa el encabezado Range en su respuesta para especificar los bytes que ha recibido hasta el momento.  Por ejemplo, un encabezado Range de 0-299999 indica que se han recibido los primeros 300.000 bytes del archivo.
  3. Suba los datos restantes. Por último, ahora que ya sabes dónde reanudar la solicitud, envía los datos restantes o el fragmento actual. Ten en cuenta que, en ambos casos, debes tratar los datos restantes como un fragmento independiente, por lo que debes enviar el encabezado Content-Range cuando reanudes la subida.
Ejemplo: Reanudar una subida interrumpida

1) Solicita el estado de la subida.

En la siguiente solicitud se usa el encabezado Content-Range para indicar que se desconoce la posición actual en el archivo de 2.000.000 bytes.

PUT {session_uri} HTTP/1.1
Content-Length: 0
Content-Range: bytes */2000000

2) Extrae de la respuesta el número de bytes que se han subido hasta el momento.

La respuesta del servidor usa la cabecera Range para indicar que ha recibido los primeros 43 bytes del archivo. Usa el valor superior del encabezado Range para determinar dónde empezar la subida reanudada.

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42

Nota: Es posible que la respuesta de estado sea 201 Created o 200 OK si la subida se ha completado. Esto puede ocurrir si la conexión se interrumpe después de que se hayan subido todos los bytes, pero antes de que el cliente reciba una respuesta del servidor.

3) Reanuda la subida desde el punto en el que se interrumpió.

La siguiente solicitud reanuda la subida enviando los bytes restantes del archivo, empezando por el byte 43.

PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

Prácticas recomendadas

Cuando subas contenido multimedia, te recomendamos que tengas en cuenta algunas prácticas recomendadas relacionadas con la gestión de errores.

  • Reanuda o vuelve a intentar las subidas que fallen debido a interrupciones de la conexión o a cualquier error 5xx, incluidos los siguientes:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Usa una estrategia de tiempo de espera exponencial si se devuelve algún error del servidor 5xx al reanudar o volver a intentar las solicitudes de subida. Estos errores pueden producirse si un servidor está sobrecargado. El retroceso exponencial puede ayudar a aliviar este tipo de problemas durante los periodos de gran volumen de solicitudes o de tráfico de red intenso.
  • Otros tipos de solicitudes no se deben gestionar con un tiempo de espera exponencial, pero puedes volver a intentar enviar algunas de ellas. Cuando vuelvas a intentar enviar estas solicitudes, limita el número de veces que lo haces. Por ejemplo, tu código podría limitar los reintentos a diez o menos antes de informar de un error.
  • Gestiona los errores 404 Not Found y 410 Gone al hacer subidas reanudables reiniciando toda la subida desde el principio.

Tiempo de espera exponencial

El tiempo de espera exponencial es una estrategia de gestión de errores estándar para las aplicaciones de red en la que el cliente vuelve a intentar periódicamente una solicitud fallida durante un periodo de tiempo cada vez mayor. Si un volumen elevado de solicitudes o un tráfico de red intenso provoca que el servidor devuelva errores, el retroceso exponencial puede ser una buena estrategia para gestionar esos errores. Por el contrario, no es una estrategia adecuada para abordar errores que no estén relacionados con el volumen de la red o los tiempos de respuesta, como las credenciales de autorización no válidas o los errores de archivo no encontrado.

Si se usa correctamente, el retardo exponencial aumenta la eficiencia del uso del ancho de banda, reduce el número de solicitudes necesarias para obtener una respuesta correcta y maximiza el rendimiento de las solicitudes en entornos simultáneos.

A continuación se indica el flujo para implementar el retardo exponencial simple:

  1. Realizar una solicitud a la API.
  2. Recibir una respuesta HTTP 503, que indica que debes volver a intentar enviar la solicitud.
  3. Espera 1 segundo más random_number_milliseconds y vuelve a intentar la solicitud.
  4. Recibir una respuesta HTTP 503, que indica que debes volver a intentar enviar la solicitud.
  5. Espera 2 segundos más random_number_milliseconds y vuelve a intentar la solicitud.
  6. Recibir una respuesta HTTP 503, que indica que debes volver a intentar enviar la solicitud.
  7. Espera 4 segundos más random_number_milliseconds y vuelve a intentar la solicitud.
  8. Recibir una respuesta HTTP 503, que indica que debes volver a intentar enviar la solicitud.
  9. Espera 8 segundos más random_number_milliseconds y vuelve a intentar la solicitud.
  10. Recibir una respuesta HTTP 503, que indica que debes volver a intentar enviar la solicitud.
  11. Espera 16 segundos más random_number_milliseconds y vuelve a intentar la solicitud.
  12. Detenerlo. Informa o registra un error.

En el flujo anterior, random_number_milliseconds es un número aleatorio de milésimas de segundo menor o igual que 1000. Esto es necesario, ya que introducir un pequeño retraso aleatorio ayuda a distribuir la carga de forma más uniforme y evita la posibilidad de que el servidor se sobrecargue. El valor de random_number_milliseconds debe volverse a definir después de cada espera.

Nota: La espera siempre es (2 ^ n) + random_number_milliseconds, donde n es un entero que se incrementa monotónicamente y que se define inicialmente como 0. El número entero n se incrementa en 1 en cada iteración (cada solicitud).

El algoritmo está configurado para terminar cuando n es 5. Este límite impide que los clientes vuelvan a intentar la operación indefinidamente. El resultado es un retraso total de aproximadamente 32 segundos antes de que una solicitud se considere "un error irrecuperable". Puedes usar un número máximo de reintentos más alto, sobre todo si se está subiendo un archivo grande. Sin embargo, asegúrate de limitar el retraso de los reintentos a un valor razonable, por ejemplo, menos de un minuto.

Guías de bibliotecas de cliente de APIs