2015-09-03 15 views
13

Sto utilizzando la libreria client API per PHP (Beta) per lavorare con api unità google, Finora posso autorizzare e e caricare un file in chuncks . Secondo il documentation, dovrebbe essere preso questi tre passaggi per caricare un file:fare richieste e gestire le risposte per il caricamento resumable: Google Drive API [php]

  • avviare una sessione ripristinabile.
  • Salvare l'URI della sessione ripristinabile.
  • Carica il file.

Quale penso che la libreria client gestisca. Anche in questo caso, in base alla documentazione, se voglio mostrare il progresso o resume an interrupted upload, o per gestire gli errori ho bisogno di catturare la risposta e anche in grado di inviare domande come questa:

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

Ma non ho idea come dovrei fare tale richiesta e da dove posso ottenere la risposta, il codice php che sto usando per caricare, come qualsiasi altro codice php, restituisce solo i valori quando viene eseguito, che è quando il caricamento è fatto. qui è la funzione che sto usando per caricare i file (può essere ripristinato):

function uploadFile($service,$client,$filetoUpload,$parentId){ 
    $file = new Google_Service_Drive_DriveFile(); 
    $file->title = $filetoUpload['name']; 
    $chunkSizeBytes = 1 * 1024 * 1024; 

    // Set the parent folder. 
     if ($parentId != null) { 
     $parent = new Google_Service_Drive_ParentReference(); 
     $parent->setId($parentId); 
     $file->setParents(array($parent)); 
     } 

    // Call the API with the media upload, defer so it doesn't immediately return. 
    $client->setDefer(true); 
    $request = $service->files->insert($file); 

    // Create a media file upload to represent our upload process. 
    $media = new Google_Http_MediaFileUpload(
     $client, 
     $request, 
     $filetoUpload['type'], 
     null, 
     true, 
     $chunkSizeBytes 
    ); 
    $media->setFileSize(filesize($filetoUpload['tmp_name'])); 

    // Upload the various chunks. $status will be false until the process is 
    // complete. 
    $status = false; 
    $handle = fopen($filetoUpload['tmp_name'], "rb"); 

    while (!$status && !feof($handle)) { 
     set_time_limit(120);  
     $chunk = fread($handle, $chunkSizeBytes); 
     $status = $media->nextChunk($chunk); 
    } 

    // The final value of $status will be the data from the API for the object 
    // that has been uploaded. 
    $result = false; 
    if($status != false) { 
     $result = $status; 
     set_time_limit(30); 
     echo "<pre>"; 
     print_r($result); 
    } 

    fclose($handle); 
    // Reset to the client to execute requests immediately in the future. 
    $client->setDefer(false); 
} 

dovrei fare un file php separato per gestire queste richieste? in tal caso, come dovrebbe indicare quale stato del file sto richiedendo? Grazie.

risposta

3

Appare, l'API del client BETA non supporta il ripristino dei caricamenti. Si prega di vedere this issue su Github, che chiede di risolvere questo. Ovviamente dovrebbe essere facile modificare la classe (vedi sotto) e creare una richiesta Pull per abilitare il supporto per riprendere i caricamenti esistenti quando viene fornito l'URL della sessione.

Tuttavia, c'è un modo semplice per ottenere lo stato di avanzamento, dopo un pezzo è stato caricato. L'oggetto Google_Http_MediaFileUpload ($media nell'esempio) ha un metodo pubblico chiamato 'getProgress' che può essere chiamato in qualsiasi momento. (Si prega di dare un'occhiata allo source code della libreria client API).

Per ottenere lo stato di caricamento, aggiungerei un parametro per modificare la precisione del progresso regolando la dimensione del blocco. Poiché vengono utilizzati più blocchi, maggiore è il sovraccarico del protocollo, impostando la precisione il più basso possibile dovrebbe essere evitato.

Pertanto, è possibile modificare il codice sorgente, come di seguito all'uscita i progressi dopo ogni pezzo:

function uploadFile($service,$client,$filetoUpload,$parentId,$progressPrecision = 1){ 
$file = new Google_Service_Drive_DriveFile(); 
$file->title = $filetoUpload['name']; 
$filesize = filesize($filetoUpload['tmp_name']); 
//minimum chunk size needs to be 256K 
$chunkSizeBytes = min($filesize/100 * $progressPrecision, 262144); 

// Set the parent folder. 
    if ($parentId != null) { 
    $parent = new Google_Service_Drive_ParentReference(); 
    $parent->setId($parentId); 
    $file->setParents(array($parent)); 
    } 

// Call the API with the media upload, defer so it doesn't immediately return. 
$client->setDefer(true); 
$request = $service->files->insert($file); 

// Create a media file upload to represent our upload process. 
$media = new Google_Http_MediaFileUpload(
    $client, 
    $request, 
    $filetoUpload['type'], 
    null, 
    true, 
    $chunkSizeBytes 
); 
$media->setFileSize($filesize); 

...

while (!$status && !feof($handle)) { 
    set_time_limit(120);  
    $chunk = fread($handle, $chunkSizeBytes); 
    $status = $media->nextChunk($chunk); 
    if(!$status){ //nextChunk() returns 'false' whenever the upload is still in progress 
    echo 'sucessfully uploaded file up to byte ' . $media->getProgress() . 
    ' which is ' . ($media->getProgress()/$chunkSizeBytes) . '% of the whole file'; 
    } 
} 

Spero che questo aiuti. Vedrò se riesco a trovare un po 'di tempo per aggiungere il supporto al curriculum alla libreria del cliente.

MODIFICA: secondo this doc, i blocchi devono essere grandi almeno 256 KB. Modificato nel codice.

EDIT2: ho appena aggiunto un Pull request Per aggiungere la funzione di ripresa.Se viene rifiutato, è ancora possibile decidere se per te sarebbe corretto modificare/estendere il client. Se viene accettato, basta memorizzare il valore restituito di $media->getResumeUri() in un database e chiamare in seguito $media->resume($previously_stored_return_value) dopo l'istanziazione per riprendere il processo.

+0

Grazie per la risposta, penso che il progresso dovrebbe essere chiamato da un php o una funzione separata perché questo restituisce tutti i dati di stato solo quando lo script è stato eseguito, ovvero quando viene caricato l'intero file. Per il caricamento ripristinabile, pensi che sarebbe meglio lavorare con node.js o javascript (+ python) o può essere fatto con php? queste librerie supportano il caricamento ripristinabile? –

+0

Penso che questo genererebbe molto più mal di testa che renderlo più facile. La causa per l'output di apparire dopo che tutto è stato completato è il buffer di output (cercare SO per vedere come disabilitarlo). Per riprendere il caricamento, è necessario salvare alcune informazioni di sessione, il posto migliore sarebbe un database. Il modo più semplice sarebbe di serializzare l'intero oggetto '$ media' e di non serializzarlo in un altro script per riprenderlo. – tillz

+0

Se non è un'opzione per disabilitare il buffer di output (probabilmente in un ambiente di hosting condiviso), è comunque possibile modificare la riga 'echo 'suc' ... per salvare l'avanzamento in un database e modificare il lato client (supponendo JavaScript) per richiedere questo stato ogni secondo. – tillz

0

Sulla prima istanza, effettuare una chiamata di upload e ottenere il resumeUri:

$chunk = fread($handle, 1*1024*1024); 
    $result = $media->nextChunk($chunk); 

    $resumeUri = $media->getResumeUri(); 
    $offset = ftell($handle); 

Sulla seconda istanza utilizzare lo stesso resumeUri per riprendere l'upload da dove abbiamo lasciato fuori chiamando resume() funzione prima nextChunk() funzione:

if ($resumeUri) { 
    $media->resume($resumeUri); 
} 

fseek($handle, $offset);  
$chunk = fread($handle, 1*1024*1024); 

$result = $media->nextChunk($chunk); 

Ripetere la procedura fino la variabile $result ha valore truthy.

+0

@Rintain Spero che questo aiuti, nel caso in cui non hai ancora trovato la soluzione – Rifaideen

Problemi correlati