Подтвердить что ты не робот

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

Я использую клиентскую библиотеку API для PHP (бета) для работы с google drive 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);
}

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

4b9b3361

Ответ 1

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

Однако, есть простой способ добиться прогресса после того, как кусок был загружен. 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);

...

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) после создания экземпляра, чтобы возобновить процесс.

Ответ 2

В первом случае сделайте вызов для загрузки и получите 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 не имеет правдивого значения.