Caricare immagini con l'API Play Games Services Publishing

L'API Play Games Services Publishing ti consente di caricare un'immagine per una risorsa di gioco.

Opzioni di caricamento

L'API Play Games Services Publishing ti consente di caricare determinati tipi di dati binari o contenuti multimediali. Le caratteristiche specifiche dei dati che puoi caricare sono specificate nella pagina di riferimento per qualsiasi metodo che supporti i caricamenti di contenuti multimediali:

  • Dimensione massima del file di caricamento: la quantità massima di dati che puoi archiviare con questo metodo.

  • Tipi MIME multimediali accettati: i tipi di dati binari che puoi archiviare utilizzando questo metodo.

Puoi effettuare richieste di caricamento in uno dei seguenti modi. Specifica il metodo che stai utilizzando con il parametro di richiesta uploadType.

  • Caricamento semplice: uploadType=media. Per il trasferimento rapido di file più piccoli, ad esempio, 5 MB o meno.

  • Caricamento multiparte: uploadType=multipart. Per il trasferimento rapido di file e metadati più piccoli, trasferisce il file insieme ai metadati che lo descrivono, il tutto in un'unica richiesta.

  • Caricamento ripristinabile: uploadType=resumable. Per un trasferimento affidabile, soprattutto con file più grandi. Con questo metodo, utilizzi una richiesta di avvio della sessione che, facoltativamente, può includere metadati. Si tratta di una buona strategia da utilizzare per la maggior parte delle applicazioni, poiché funziona anche per file più piccoli al costo di una richiesta HTTP aggiuntiva per caricamento.

Quando carichi contenuti multimediali, utilizzi un URI speciale. Infatti, i metodi che supportano i caricamenti multimediali hanno due endpoint URI:

  • L'URI /upload, per il contenuto multimediale. Il formato dell'endpoint di caricamento è l'URI standard della risorsa con il prefisso "/upload". Usa questo URI durante il trasferimento dei dati multimediali stessi.

    Esempio: POST /upload/games/v1configuration/images/resourceId/imageType/imageType

  • L'URI standard della risorsa, per i metadati. Se la risorsa contiene campi di dati, questi vengono utilizzati per archiviare i metadati che descrivono il file caricato. Puoi utilizzare questo URI durante la creazione o l'aggiornamento dei valori dei metadati.

    Esempio: POST /games/v1configuration/images/resourceId/imageType/imageType

Caricamento semplice

Il metodo più semplice per caricare un file consiste nell'eseguire una semplice richiesta di caricamento. Questa opzione è ideale quando si verifica una delle seguenti condizioni:

  • Il file è abbastanza piccolo per essere caricato nuovamente completamente in caso di problemi di connessione.

  • Nessun metadato da inviare. Questo può verificarsi se prevedi di inviare metadati per questa risorsa in una richiesta separata o se non sono supportati o disponibili metadati. Per utilizzare il caricamento semplice, effettua una richiesta POST o PUT all'URI /upload del metodo e aggiungi il parametro di query uploadType=media. Ecco alcuni esempi:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media

Le intestazioni HTTP da utilizzare quando si effettua una semplice richiesta di caricamento includono:

  • Content-Type. Impostato su uno dei tipi di dati multimediali per il caricamento accettati del metodo, specificati nel riferimento dell'API Publishing.

  • Content-Length. Imposta il numero di byte da caricare. Non è necessaria se utilizzi la codifica del trasferimento in blocchi.

Esempio: caricamento semplice

L'esempio seguente mostra l'utilizzo di una semplice richiesta di caricamento per l'API Play Games Services Publishing.

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

Se la richiesta ha esito positivo, il server restituisce il codice di stato HTTP 200 OK insieme agli eventuali metadati. Ecco alcuni esempi:

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Caricamento multiparte

Se hai metadati che vuoi inviare insieme ai dati da caricare, puoi effettuare una singola richiesta multipart/related. Si tratta della scelta ideale se i dati inviati sono sufficientemente piccoli da poter essere ricaricati completamente in caso di problemi di connessione.

Per utilizzare il caricamento multiparte, effettua una richiesta POST o PUT all'URI /upload del metodo e aggiungi il parametro di ricerca uploadType=multipart. Ecco alcuni esempi:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart

Le intestazioni HTTP di primo livello da utilizzare per una richiesta di caricamento con più parti includono:

-Content-Type. Impostalo su multiparte/correlato e includi la stringa limite che stai utilizzando per identificare le parti della richiesta.

-Content-Length. Impostato sul numero totale di byte nel corpo della richiesta. La parte multimediale della richiesta deve essere inferiore alla dimensione massima del file specificata per questo metodo.

Il corpo della richiesta è formattato come tipo di contenuti multiparte/correlati RFC2387 e contiene esattamente due parti. Le parti sono identificate da una stringa di confine e l'ultima stringa di confine è seguita da due trattini.

Ogni parte della richiesta con più parti richiede un'intestazione Content-Type aggiuntiva:

  • Parte dei metadati: deve essere inserita per prima e Content-Type deve corrispondere a uno dei formati di metadati accettati.

  • Parte multimediale: deve essere seconda e Content-Type deve corrispondere a uno dei tipi MIME multimediali accettati del metodo.

Consulta il riferimento dell'API Publishing per conoscere l'elenco dei tipi MIME multimediali accettati e i limiti di dimensione dei file caricati in ciascun metodo.

Esempio: caricamento multiparte

L'esempio seguente mostra una richiesta di caricamento in più parti per l'API Play Games Services Publishing.

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

Se la richiesta ha esito positivo, il server restituisce il codice di stato HTTP 200 OK insieme a tutti i metadati:

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Caricamento ripristinabile

Per caricare i file di dati in modo più affidabile, puoi utilizzare il protocollo di caricamento ripristinabile. Questo protocollo consente di riprendere un'operazione di caricamento dopo che un errore di comunicazione ha interrotto il flusso di dati. È particolarmente utile se stai trasferendo file di grandi dimensioni e la probabilità di interruzione della rete o altri errori di trasmissione è elevata, ad esempio quando carichi un file da un'app client per dispositivi mobili. Può anche ridurre l'utilizzo della larghezza di banda in caso di errori di rete, in quanto non è necessario riavviare dall'inizio i caricamenti di file di grandi dimensioni.

I passaggi per l'utilizzo di un caricamento ripristinabile includono:

  1. Avvia una sessione ripristinabile. Effettua una richiesta iniziale all'URI di caricamento che includa i metadati, se presenti.

  2. Salva l'URI della sessione ripristinabile. Salva l'URI della sessione restituito nella risposta della richiesta iniziale; lo utilizzerai per le restanti richieste di questa sessione. Carica il file.

  3. Invia il file multimediale all'URI della sessione ripristinabile.

Inoltre, le app che utilizzano un caricamento ripristinabile devono avere il codice per riprendere un caricamento interrotto. Se un caricamento viene interrotto, scopri quanti dati sono stati ricevuti correttamente e riprendi il caricamento partendo da quel punto.

Avviare una sessione ripristinabile

Per avviare un caricamento ripristinabile, effettua una richiesta POST o PUT all'URI /upload del metodo e aggiungi il parametro di ricerca uploadType=resumable. Ecco alcuni esempi:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable

Per questa richiesta di avvio, il corpo è vuoto o contiene solo i metadati; verranno trasferiti i contenuti effettivi del file che vuoi caricare nelle richieste successive.

Utilizza le seguenti intestazioni HTTP con la richiesta iniziale:

  • X-Upload-Content-Type. Imposta il tipo MIME multimediale dei dati di caricamento da trasferire nelle richieste successive.

  • X-Upload-Content-Length. Imposta il numero di byte dei dati di caricamento da trasferire nelle richieste successive. Se la lunghezza non è nota al momento della richiesta, puoi omettere questa intestazione.

  • Se fornisci i metadati: Content-Type. Impostato in base al tipo di dati dei metadati.

  • Content-Length. Imposta il numero di byte forniti nel corpo di questa richiesta iniziale. Non è necessaria se utilizzi la codifica del trasferimento in blocchi.

Consulta il riferimento per l'API Publishing per ciascun metodo per conoscere l'elenco dei tipi MIME multimediali accettati e i limiti di dimensione dei file caricati.

Esempio: richiesta di avvio della sessione ripristinabile

L'esempio seguente mostra come avviare una sessione ripristinabile per l'API Play Games Services Publishing.

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
}

Nella sezione successiva viene descritto come gestire la risposta.

Salva l'URI della sessione ripristinabile

Se la richiesta di avvio della sessione ha esito positivo, il server API risponde con un codice di stato HTTP 200 OK. Inoltre, fornisce un'intestazione Location che specifica l'URI della sessione ripristinabile. L'intestazione Location, mostrata nell'esempio riportato di seguito, include una parte del parametro di ricerca upload_id che fornisce l'ID di caricamento univoco da utilizzare per questa sessione.

Esempio: risposta di avvio della sessione ripristinabile

Ecco la risposta alla richiesta nel passaggio 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

Il valore dell'intestazione Location, come mostrato nell'esempio di risposta riportato sopra, è l'URI della sessione che utilizzerai come endpoint HTTP per eseguire il caricamento effettivo del file o eseguire query sullo stato del caricamento.

Copia e salva l'URI della sessione in modo da poterlo utilizzare per le richieste successive.

Caricamento del file

Per caricare il file, invia una richiesta PUT all'URI di caricamento ottenuto nel passaggio precedente. Il formato della richiesta di caricamento è il seguente:

PUT session_uri

Le intestazioni HTTP da utilizzare quando si effettuano richieste di caricamento di file ripristinabili includono Content-Length. Impostalo sul numero di byte che stai caricando in questa richiesta, che in genere corrisponde alle dimensioni del file di caricamento.

Esempio: richiesta di caricamento di un file ripristinabile

Ecco una richiesta ripristinabile per caricare l'intero file PNG da 2.000.000 di byte per l'esempio corrente.

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

Se la richiesta ha esito positivo, il server risponde con un HTTP 201 Created, insieme a tutti i metadati associati alla risorsa. Se la richiesta iniziale della sessione ripristinabile fosse un PUT, per aggiornare una risorsa esistente la risposta corretta sarebbe 200 OK, insieme a tutti i metadati associati alla risorsa.

Se la richiesta di caricamento viene interrotta o se ricevi una risposta HTTP 503 Service Unavailable o qualsiasi altra risposta 5xx dal server, segui la procedura descritta in Riprendere un caricamento interrotto.


Carica il file in blocchi

Con i caricamenti ripristinabili, puoi suddividere un file in blocchi e inviare una serie di richieste per caricare ogni blocco in sequenza. Questo non è l'approccio preferito, poiché alle richieste aggiuntive sono associati costi di prestazioni e in genere non è necessario. Tuttavia, potrebbe essere necessario utilizzare la suddivisione in blocchi per ridurre la quantità di dati trasferiti in ogni singola richiesta. Ciò è utile quando esiste un limite di tempo fisso per le singole richieste, come avviene per determinate classi di richieste di Google App Engine. Ti consente inoltre di fornire indicazioni sull'avanzamento del caricamento per i browser precedenti che non supportano per impostazione predefinita l'avanzamento del caricamento.

Se intendi caricare i dati in blocchi, è necessaria anche l'intestazione Content-Range, insieme all'intestazione Content-Length obbligatoria per il caricamento completo dei file:

  • Content-Length. Impostalo sulla dimensione del blocco o su un valore inferiore, come nel caso dell'ultima richiesta.

  • Content-Range: imposta questa opzione per mostrare i byte del file che stai caricando. Ad esempio, Content-Range: bytes 0-524287/2000000 indica che stai fornendo i primi 524.288 byte (256 x 1024 x 2) in un file da 2.000.000 byte.

Esempio: richiesta di caricamento di file in blocchi ripristinabile

Una richiesta che invia i primi 524.288 byte potrebbe avere il seguente aspetto:

PUT {session_uri} HTTP/1.1
Host: www.googleapis.com
Content-Length: 524288
Content-Type: image/png
Content-Range: bytes 0-524287/2000000

bytes 0-524288

Se la richiesta ha esito positivo, il server risponde con 308 Resume Incomplete, insieme a un'intestazione Range che identifica il numero totale di byte archiviati finora:

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: bytes=0-524287

Utilizza il valore più alto restituito nell'intestazione Range per determinare da dove iniziare il blocco successivo. Continua con PUT ogni blocco del file fino al caricamento dell'intero file.

Se la richiesta PUT di un blocco viene interrotta o se ricevi una risposta HTTP 503 Service Unavailable o qualsiasi altra risposta 5xx dal server, segui la procedura descritta in Riprendere un caricamento interrotto, ma invece di caricare il resto del file, continua semplicemente a caricare i blocchi da quel punto.

Note importanti:

  • Assicurati di utilizzare l'intestazione Range nella risposta per determinare da dove iniziare il blocco successivo; non dare per scontato che il server abbia ricevuto tutti i byte inviati nella richiesta precedente.

  • Ogni URI di caricamento ha una durata limitata e alla fine scade (entro un giorno circa, se non utilizzato). Per questo motivo, è preferibile avviare un caricamento ripristinabile non appena ottieni l'URI del caricamento e riprendere un caricamento interrotto poco dopo l'interruzione.

  • Se invii una richiesta con un ID sessione di caricamento scaduto, il server restituisce un codice di stato 404 Not Found. Quando si verifica un errore irreversibile nella sessione di caricamento, il server restituisce un codice di stato 410 Gone. In questi casi, devi avviare un nuovo caricamento ripristinabile, ottenere un nuovo URI di caricamento e avviare il caricamento dall'inizio utilizzando il nuovo endpoint.

Quando il caricamento del file è completo, il server risponde con HTTP 201 Created insieme a tutti i metadati associati alla risorsa. Se la richiesta aggiornasse un'entità esistente anziché crearne una nuova, il codice di risposta HTTP per un caricamento completato sarebbe stato 200 OK.


Riprendere un caricamento interrotto

Se una richiesta di caricamento viene terminata prima di ricevere una risposta o se ricevi una risposta HTTP 503 Service Unavailable dal server, devi riprendere il caricamento interrotto. Per riprendere un caricamento interrotto:

  1. Stato della richiesta. Query sullo stato attuale del caricamento inviando una richiesta PUT vuota all'URI di caricamento. Per questa richiesta, le intestazioni HTTP devono includere un'intestazione Content-Range che indica che la posizione corrente nel file è sconosciuta. Ad esempio, imposta Content-Range su */2000000 se la lunghezza totale del file è 2.000.000. Se non conosci la dimensione intera del file, imposta l'intervallo di contenuti su */*.

  2. Ottieni il numero di byte caricati. Elabora la risposta alla query sullo stato. Il server utilizza l'intestazione Range nella risposta per specificare i byte ricevuti finora. Ad esempio, un'intestazione Range di 0-299999 indica che sono stati ricevuti i primi 300.000 byte del file.

  3. Carica i dati rimanenti. Infine, ora che sai dove riprendere la richiesta, invia i dati rimanenti o il blocco attuale. Tieni presente che in entrambi i casi devi trattare i dati rimanenti come un blocco separato, quindi devi inviare l'intestazione Content-Range quando riprendi il caricamento.

Esempio: riprendere un caricamento interrotto

  1. Richiedi lo stato del caricamento. La richiesta seguente utilizza l'intestazione Content-Range per indicare che la posizione corrente nel file da 2.000.000 byte è sconosciuta.

    PUT {session_uri} HTTP/1.1
    Content-Length: 0
    Content-Range: bytes */2000000
    
  2. Estrai il numero di byte caricati finora dalla risposta. La risposta del server utilizza l'intestazione Range per indicare che finora ha ricevuto i primi 43 byte del file. Utilizza il valore superiore dell'intestazione Intervallo per determinare da dove avviare il caricamento ripreso.

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42
  1. Riprendi il caricamento dal punto in cui è stato interrotto. La seguente richiesta ripristina il caricamento inviando i byte rimanenti del file, a partire dal byte 43.
PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

Best practice

Quando carichi contenuti multimediali, è utile conoscere alcune best practice relative alla gestione degli errori.

  • Riprendi o riprova i caricamenti che non riescono a causa di interruzioni della connessione o di eventuali errori 5xx, tra cui:

    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Utilizza una strategia di backoff esponenziale se viene restituito un errore del server 5xx al momento del ripristino o di un nuovo tentativo di caricamento delle richieste. Questi errori possono verificarsi in caso di sovraccarico del server. Il backoff esponenziale può aiutare ad alleviare questo tipo di problemi durante i periodi di volume elevato di richieste o traffico di rete intenso.

  • Altri tipi di richieste non dovrebbero essere gestiti dal backoff esponenziale, ma puoi comunque riprovare un certo numero. Limita il numero di nuovi tentativi di queste richieste. Ad esempio, il codice potrebbe limitare a dieci nuovi tentativi o meno prima di segnalare un errore.

  • Gestisci gli errori 404 Not Found e 410 Gone durante i caricamenti ripristinabili, ricominciando l'intero caricamento dall'inizio.

Backoff esponenziale

Il backoff esponenziale è una strategia di gestione degli errori standard per le applicazioni di rete in cui il client riprova periodicamente a effettuare una richiesta non riuscita per un periodo di tempo crescente. Se un volume elevato di richieste o un traffico di rete intenso fa sì che il server restituisca errori, il backoff esponenziale può essere una buona strategia per la gestione di questi errori. Al contrario, non è una strategia pertinente per la gestione di errori non correlati al volume di rete o ai tempi di risposta, come credenziali di autorizzazione non valide o errori file non trovato.

Se usato correttamente, il backoff esponenziale aumenta l'efficienza dell'utilizzo della larghezza di banda, riduce il numero di richieste necessarie per ottenere una risposta corretta e massimizza la velocità effettiva delle richieste in ambienti simultanei.

Il flusso per l'implementazione di un backoff esponenziale semplice è il seguente:

  1. Effettua una richiesta all'API.
  2. Ricevi una risposta HTTP 503, che indica che devi ritentare la richiesta.
  3. Attendi 1 secondo + numero_casuale_di_millisecondi e riprova.
  4. Ricevi una risposta HTTP 503, che indica che devi ritentare la richiesta.
  5. Attendi 2 secondi + numero_casuale_di_millisecondi e riprova.
  6. Ricevi una risposta HTTP 503, che indica che devi ritentare la richiesta.
  7. Attendi 4 secondi + numero_casuale_di_millisecondi e riprova.
  8. Ricevi un HTTP 503 response, che indica che devi ritentare la richiesta.
  9. Attendi 8 secondi + numero_casuale_di_millisecondi e riprova.
  10. Ricevi un HTTP 503 response, che indica che devi ritentare la richiesta.
  11. Attendi 16 secondi + numero_casuale_di_millisecondi e riprova.
  12. Interrompi. Segnala o registra un errore.

Nell'elenco precedente, random_number_milliseconds è un numero casuale di millisecondi inferiore o uguale a 1000. Questa operazione è necessaria, poiché l'introduzione di un piccolo ritardo casuale consente di distribuire il carico in modo più uniforme ed evitare la possibilità di aggiungere timbri al server. Il valore di random_number_millisecondi deve essere ridefinito dopo ogni attesa.

L'algoritmo è impostato per terminare quando n è 5. Questo limite impedisce ai client di riprovare all'infinito, e genera un ritardo totale di circa 32 secondi prima che una richiesta venga considerata "un errore irreversibile". Un numero massimo di tentativi maggiore è consentito, soprattutto se è in corso un caricamento lungo; assicurati solo di limitare il ritardo tra tentativi a un valore ragionevole, ad esempio inferiore a un minuto.

Guide della libreria client API