Простая работа с Google Drive API

foreach ($file[‘name’] as $idx => $name) {
$result[$idx] = [
‘name’ => $name,
‘type’ => $file[‘type’][$idx],
‘tmp_name’ => $file[‘tmp_name’][$idx],
‘error’ => $file[‘error’][$idx],
‘size’ => $file[‘size’][$idx]
];
}
}
return $result;
}

/**
* Вспомогательная функция для отладки
*
* @param $data
*/
function varDumper($data){
echo ‘<pre>’;
print_r($data);
echo ‘</pre>’;
}

Внимание!

Необходимо настроить в настройка переадресацию, например, у меня http://localhost.

Для методов $client->setClientId() и $client->setClientSecret() нужно установить значения, которые Вы возьмете из настроек своего проекта в Google API Console.

Дополнительно вынес рекурсивную функцию в отдельный класс, который расположен в файле BuildTree.php. По факту функцию можно было бы оставить в файле index.php, но планировалось немного большее, однако как всегда не хватило времени на реализацию.

Листинг файла BuildTree.php

<?php

class BuildTree
{
  /**
   * Рекурсивное создание дерева элементов
   *
   * @param array  $elements Массив элементов
   * @param string $parentId Идентификатор корневого элемента
   * @return array
   */
  public function makeTree(Array &$elements, $parentId = '') : array
  {
    $branch = [];
    foreach ($elements as &$element) {
      if ($element['parentId'] == $parentId) {
        $element['children'] = $this->makeTree($elements, $element['id']);
        $branch[$element['id']] = $element;
        unset($element);
      }
    }
    return $branch;
  }
}

Хочу отметить, что функция написана для PHP 7.0.

Листинг файла для отображения создания новой папки.

<h3>Новая папка</h3>
<form method="post">
  <label>Название папки<br>
    <input type="text" name="newFolder" value="">
  </label>
  <input type="submit" value="Создать">
</form>

Листинг файла для отображения загрузки файлов.

<h3>Загрузить файлы</h3>
<form method="post" enctype="multipart/form-data">
  <label>Выберите файлы:<br>
    <input type="file" name="Files[]" multiple>
  </label><br>
  <p>
    <input type="submit" value="Загрузить файлы">
  </p>
</form>

Вот и все основные файлы. Если все сделали правильно, то должно работать. В конце статьи добавлю ссылку на архив (если кто-то не хочет заморачиваться с composer).

А вот и результаты мое работы. Как Вы заметили, в коде нет особых проверок, т.к. это всего лишь пример, а не реальный рабочий проект.

Если появились вопросы, пожалуйста, задавайте, а я постараюсь на них ответить. Спасибо и до новых встреч.

Полезные ссылки

  1. Getting Started
  2. Google APIs Client Library for PHP
  3. Google Drive REST API
  4. Пример работы с Google Drive API (исходники на github)
  5. Sample Google Drive API (исходники в архиве zip)

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

45 thoughts on “Простая работа с Google Drive API

  • 05.07.2018 в 12:18
    Permalink

    Добрый день! Развернул архив на хостинге и получил следующее ошибку:
    Parse error: syntax error, unexpected ‘:’, expecting ‘;’ or ‘{‘ in /home/host1475025/***domain***/htdocs/www/google-drive-amo/BuildTree.php on line 12

    Вместо ***domain*** соответственно свой домен в котором лежит папка google-drive-amo.
    Заранее благодарен!

    • 05.07.2018 в 12:45
      Permalink

      Добрый день! Необходимо проверить, какая версия PHP установлена на сервере. Здесь требуется минимум PHP 7.0.
      А еще можно строку public function makeTree(Array &$elements, $parentId = '') : array заменить на
      public function makeTree(Array &$elements, $parentId = '') в файле BuildTree.php.
      А так все должно работать. Проверялось неоднократно.

      • 05.07.2018 в 14:35
        Permalink

        Спасибо, помогла замена строки в файле BuildTree.php.
        Сейчас след. ошибку возвращает гугл:

        400. That’s an error.
        Error: redirect_uri_mismatch
        The redirect URI in the request, http://***domain***/google-drive-amo/index.php, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit: https://console.developers.google.com/apis/credentials/oauthclient/************-9r04kt1hsj25dl3bktal1kvjqe350so5.apps.googleusercontent.com?project=********

        Похоже я неверно заполнил след. вкладку. ( скрин https://yadi.sk/i/ZO_oSc0S3YoUAD )

        • 05.07.2018 в 15:18
          Permalink

          В поле «Разрешенные URI перенаправления» необходимо написать путь к index.php файлу.
          В примере все размещалось на localhost. У вас — это http://***domain***/google-drive-amo/.
          Здесь ***domain*** — ваше доменное имя. Если скрипт хотите разместить в корне, то просто указываете адрес сайта вместе с http.

          • 05.07.2018 в 15:44
            Permalink

            Так, разрешение акк получил. Теперь выдает след. ошибку:

            Fatal error: Uncaught InvalidArgumentException: Invalid token format in /home/host1475025/***domain***/htdocs/www/google-drive-amo/vendor/google/apiclient/src/Google/Client.php:423 Stack trace: #0 /home/host1475025/***domain***/htdocs/www/google-drive-amo/index.php(30): Google_Client->setAccessToken(Array) #1 {main} thrown in /home/host1475025/***domain***/htdocs/www/google-drive-amo/vendor/google/apiclient/src/Google/Client.php on line 423

            PHP на сервере обновил до 7.0 версии.

  • 05.07.2018 в 17:29
    Permalink

    Предыдущая ошибка пропала. Сейчас белый экран.
    1)var_dump($_SESSION[‘accessToken’]); возвращает:
    array(4) { [«access_token»]=> string(129) «**************************-iHHSBVny3yBJQyM97PVPe66XO1IqclBfgJW45jd3uJ0Hobhnp4zKbPKKhRx8hYJYfwIBrlDRTNeCslNeAyqaB8ZHmWqjvvX****» [«token_type»]=> string(6) «Bearer» [«expires_in»]=> int(3600) [«created»]=> int(1530799869) }

    1)var_dump($token]); возвращает: NULL

    • 05.07.2018 в 19:06
      Permalink

      Ну если clientId и clienSecret свои поставили, да и как видно $_SESSION[‘accessToken’]) возвращает все-таки токен.
      Не понятно почему $token возвращает [no-highlight]NULL[/no-highlight].
      Да и тут опечатка видимо [no-highlight]1)var_dump($token]);[/no-highlight]. Лишняя скобка.
      Я бы попробовал уничтожить сессию через [no-highlight]unset($_SESSION[‘accessToken’]);[/no-highlight]. Можно в браузере удалить сессию и попробовать заново smile

  • 06.07.2018 в 10:41
    Permalink

    Да, видимо ошибка в скобке была (уже забил на это) smile . В сессии все норм было, авторизацию проходил успешно. В общем все работает прекрасно, спасибо огромное! good Только у меня не заработало дерево элементов, но оно мне и не нужно было)

    • 06.07.2018 в 16:51
      Permalink

      Окей, обращайтесь. А насчет дерева элементов, возможно на самом google-диске просто нет файлов. Пустое дерево — пустой массив.

      • 10.07.2018 в 21:05
        Permalink

        Добрый вечер, Денис! Подскажите пожалуйста для чего нужны ob_start(); и ob_end_flush(); ? Можно ли обойтись без них?

        • 10.07.2018 в 23:45
          Permalink

          Добрый день! Все просто.
          Если говорить кратко, то иногда необходимо, чтобы вывод скрипта не отправлялся, т.к. появляются ошибки при выводе. Поэтому временно все что хотим вывести сохраняем в буфере. А в конце сбрасываем и отключаем буферизацию.
          ob_start — Включение буферизации вывода.
          ob_end_flush — Сбросить (отправить) буфер вывод и отключить буферизацию вывода.
          И насчет обойтись без них. Да, можно, но чтобы не было ошибок лучше сначала отправлять все заголовки, а потом уже что-то выводить.
          На данную тему можно легко найти информацию в интернете. Все шаблонизаторы работают по аналогичному принципу.

          • 11.07.2018 в 07:01
            Permalink

            Спасибо!

  • 11.07.2018 в 19:17
    Permalink

    Добрый вечер! У меня возник еще один вопрос: достаточно ли добавить до запроса на подтверждения работы с гугл диском следующую строку $client->setAccessType(‘offline’); , чтобы период жизни токена не истекал и приложение могло работало автономно без подтверждения через браузер?

    • 11.07.2018 в 19:41
      Permalink

      Добрый вечер. Я, к сожалению, не могу помнить всего API Google и библиотеки, которая его реализует.
      Однако если бегло взглянуть, то да можно воспользоваться данным методом для так сказать вечного токена.
      Насколько понял, нужно применить [no-highlight]$client->setAccessType(‘offline’);[/no-highlight], а еще [no-highlight]$client->setApprovalPrompt(‘force’);[/no-highlight] — включение запроса для токена. А то может не возвращаться токен. И, еще, надо не забыть удалить предыдущий токен.
      Но более точную информацию можно получить при обращении к библиотеке и ее документации sorry

      • 11.07.2018 в 20:09
        Permalink

        Спасибо, добавив $client->setAccessType(‘offline’); и $client->setApprovalPrompt(‘force’); включился автономный доступ. Массив $_SESSION[‘accessToken’] дополнился refresh_token’ом.

  • 28.11.2018 в 12:04
    Permalink

    всё — разобрался!
    дело было в загадочном 0AHCqnAQsA3IDUk9PVA
    непосредственно в построении дерева
    $tree = $buildTree->makeTree($files, ‘0AHCqnAQsA3IDUk9PVA’);

    у меня например совсем другое значение оказалось!
    В общем перед этой строчкой делаем var_dump($tree) и смотрим parentId у любого файла расположенного в корне — берём эти символы и пихаем вместо загадочных

    • 28.11.2018 в 18:22
      Permalink

      Добрый день! Да, всегда при проверке работы желательно включать вывод всех ошибок. Если ничего не выводится, то можно проверить выводимые данные с помощью отладочных функций. А так, специально для отладки здесь есть функция varDumper (хотя var_dump будет более подробной).

  • 28.11.2018 в 12:07
    Permalink

    попробовал form-upload-file.php из архива — не загружает sad
    при нажатии «загрузить файлы» пишет «Файл не выбран»

  • 28.11.2018 в 12:14
    Permalink

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

    /index.php?action=upload&fid=1

    получаю всегда File not found

  • 28.11.2018 в 12:25
    Permalink

    Урааа — загрузилось!!!
    fid это и есть эти загадочные символы!
    т.е. файловый идентификатор родителя
    если это корень — те же самые символы что и выше!!!

  • 28.11.2018 в 12:34
    Permalink

    ещё момент — как быть если я не браузером авторизироваться буду?
    т.е. нужно чтобы по расписанию с гугл диска загружались новые файлы на сайт

    • 28.11.2018 в 18:28
      Permalink

      В любом случае, необходимо получить разрешение для работы с диском, как раз и будет возвращен токен. А уже потом каким образом и что будете Вы делать, решать только вам.

  • 28.11.2018 в 13:00
    Permalink

    создал ключ сервисного аккаунта, авторизовался через него
    он вообще другой список файлов даёт — один файлик «Getting started.pdf»

    • 28.11.2018 в 18:27
      Permalink

      Если все выполнено правильно, то должно работать. Следует учитывать версию php, настройки сервера, ну и конечно, ваши данные для доступа к Google Drive (тут данные только для примера, хоть и реальные) smile .

  • 29.11.2018 в 06:33
    Permalink

    да, с токеном пашет — спасибо большое за статью!
    а вот с ключем сервисного аккаунта я так и не разобрался sad какой то левый список получает

    • 29.11.2018 в 18:16
      Permalink

      Да, всегда можно переписать под любую версию PHP. Для этого необходимо понимать отличия версий. В интернете полно информации. Например, в файле BuildTree.php есть функция, которая возвращает в заголовке массив, который можно убрать:
      [no-highlight]public function makeTree(Array &$elements, $parentId = »)[/no-highlight]

    • 29.11.2018 в 18:17
      Permalink

      Это пример. Данный класс действительно нужен только для построения дерева. Если дерево не нужно строить, то можно и обойтись без него smile

  • 29.11.2018 в 11:57
    Permalink

    ещё момент — за раз только 100 файлов отдаётся!
    судя по логике следующая партия — с новым токеном должна запрашиваться nextPageToken
    не в курсе — можно сразу все получить?

    • 29.11.2018 в 18:33
      Permalink

      Это наверное по умолчанию 100 файлов отдается. Если не ошибаюсь, то можно указать от 1 до 1000. Также есть параметр pageToken в который нужно вставить маркер из предыдущего ответа nextPageToken.
      Все в документации подробно описано здесь.

  • 30.11.2018 в 04:52
    Permalink

    Дока это отлично, но как эти параметры задать?
    туплю sad

    $DriveService->files->pageSize(1000);
    Fatal error: Call to undefined method Google_Service_Drive_Resource_Files::pageSize()

  • 30.11.2018 в 06:53
    Permalink

    вообще АПИ хрень
    очень часто выкидывает
    Fatal error: Uncaught exception ‘RuntimeException’ with message ‘Error creating resource: [message] fopen(): php_network_getaddresses: getaddrinfo failed

    кто же запросы через fopen() дёргает?! пипец

    • 30.11.2018 в 09:57
      Permalink

      Добрый день. Стандартная ситуация когда для получения данных используется fopen (старая и надежная функция для получения данных). Нет, зависимости, например от cUrl. Можете попробовать написать свой класс для работы с API, например через cUrl или еще как-то.
      Да и это нормальный процесс, ошибки в разработке бывают. Нужно читать документация и смотреть, что передается и что возвращается.

  • 11.08.2019 в 23:07
    Permalink

    друзья помогите настроить. чет не понимаю. залил скрипт. прописал setClientId и setClientSecret и кроме ошибки 500 не чего не получаю.

    • 11.08.2019 в 23:35
      Permalink

      Доброго времени суток. Вы же понимаете, сложно сказать, что у вас не так по одной только 500 ошибке. Ошибка серверная, проверьте версию php, должна быть от 7. А так, функция var_dump() и die() для тестирования в помощь. Видимо не все условия выполнены как в статье.

      • 12.08.2019 в 03:10
        Permalink

        да, тупанул. У меня мультиверсионность php и по умолчанию стояла 5.6. Вроде подключился, но теперь не могу вывести весь каталог — пустая страница

          • 18.08.2019 в 17:14
            Permalink

            Добрый день. Что же Вы не читаете комментарии к коду.

            [php]
            /**
            * Рекурсивное создание дерева элементов
            *
            * @param array $elements Массив элементов
            * @param string $parentId Идентификатор корневого элемента
            * @return array
            */
            public function makeTree(Array &$elements, $parentId = ») : array
            [/php]
            Следовательно, здесь должен быть — Идентификатор корневого элемента. У всех он естественно разный. Если вам видно чужие файлы, то скорее всего вы не установили свои значения в методах setClientId и setClientSecret.
            Как и где взять эти значения можно найти в Интернете.

Добавить комментарий

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: