Выполнять запросы и обрабатывать ответы для возобновляемой загрузки: Google Drive api

Я использую клиентскую библиотеку API для PHP (бета) для работы с google-приводом api, до сих пор могу разрешать и загружать файл в chuncks. Согласно документации , эти три шага должны быть предприняты для загрузки файла:

  • Начать возобновляемый сеанс.
  • Сохраните возобновляемый URI сеанса.
  • Загрузите файл.

Я думаю, что клиентская библиотека обрабатывает. Опять же, согласно документации, если я хочу показать прогресс или возобновить прерванную загрузку или обработать ошибки, мне нужно зафиксировать ответ, а также отправить такие запросы следующим образом:

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

Но я понятия не имею, как мне сделать такой запрос и откуда я могу получить ответ, php-код, который я использую для загрузки, как и любой другой php-код, возвращает значения только тогда, когда это выполняется, то есть когда загрузка готово. вот функция, которую я использую для загрузки файлов (возобновляется):

 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); } , 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); } 

Должен ли я создать отдельный файл php для обработки этих запросов? если да, то как сказать, какой статус файла я запрашиваю? Благодарю.

Явно, API клиента BETA просто не поддерживает возобновление загрузки. См. Эту проблему в Github, в которой говорится об исправлении этого вопроса . Конечно, должно быть легко изменить класс (см. Ниже) и создать запрос Pull, чтобы включить поддержку для возобновления существующих загрузок, когда будет указан URL-адрес сеанса.

Тем не менее, есть простой способ добиться прогресса после того, как кусок был загружен. Google_Http_MediaFileUpload Google_Http_MediaFileUpload ( $media в вашем примере) имеет открытый метод, называемый getProgress, который можно вызвать в любое время. (Пожалуйста, посмотрите исходный код API-клиент-библиотеки).

Чтобы получить статус загрузки, я бы добавил параметр, чтобы изменить точность выполнения, отрегулировав размер куска. Поскольку больше блоков используется, увеличивается количество служебных данных протокола, поэтому следует избегать установки как можно более низкой точности.

Таким образом, вы можете изменить исходный код, как показано ниже, для вывода прогресса после каждого фрагмента:

 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); , 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'; } } 

Надеюсь это поможет. Я посмотрю, смогу ли я найти некоторое время, чтобы добавить поддержку резюме в клиентскую библиотеку.

EDIT: согласно этому документу , куски должны быть как минимум 256 КБ. Изменено в коде.

EDIT2: Я просто добавил запрос Pull. Чтобы добавить функцию возобновления. Если он отклоняется, вы все равно можете решить, будет ли вам нормально модифицировать / расширять клиент. Если это принято, просто используйте для хранения возвращаемое значение $media->getResumeUri() в базе данных, а затем вызовите $media->resume($previously_stored_return_value) $media->getResumeUri() $media->resume($previously_stored_return_value) после создания экземпляра, чтобы возобновить процесс.

В первом случае сделайте вызов для загрузки и получите resumeUri :

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

Во втором случае используйте тот же resumeUri чтобы возобновить загрузку с того места, где мы ушли, вызвав функцию resume() перед функцией nextChunk() :

  if ($resumeUri) { $media->resume($resumeUri); } fseek($handle, $offset); $chunk = fread($handle, 1*1024*1024); $result = $media->nextChunk($chunk); 

Повторите процесс, пока переменная $result имеет правдивого значения.