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

// Вывод дерева
printTree($tree);

if (isset($_GET[‘action’])) {
switch ($_GET[‘action’]) {
// Создание новой папки
case ‘newdir’:

if (isset($_GET[‘pid’])) {
include ‘form-create-dir.php’;

if ($_POST) {
if (!empty($_POST[‘newFolder’])) {
$fileMetadata = new Google_Service_Drive_DriveFile([
‘name’ => htmlspecialchars($_POST[‘newFolder’]),
‘parents’ => [htmlspecialchars($_GET[‘pid’])],
‘mimeType’ => ‘application/vnd.google-apps.folder’
]);
$driveService->files->create($fileMetadata, [‘fields’ => ‘id’]);
header(‘Location:’ . filter_var($redirect_uri, FILTER_SANITIZE_URL));

} else {
die(‘Заполните название папки’);
}
}
}

break;

// Загрузка файлов
case ‘upload’:

if (isset($_GET[‘fid’])) {
include ‘form-upload-file.php’;

if (isset($_FILES[‘Files’]) && is_uploaded_file($_FILES[‘Files’][‘tmp_name’][0]) && ($_FILES[‘Files’][‘error’][0] == 0)) {
$files = normalizeFilesArray($_FILES);

$fileMetadata = new Google_Service_Drive_DriveFile([
‘parents’ => [htmlspecialchars($_GET[‘fid’])]
]);

foreach ($files as $file) {
$filePath = $file[‘tmp_name’];
$mimeType = $file[‘type’];

$fileMetadata->setName($file[‘name’]);
$fileMetadata->setDescription(‘Это документ ‘ . $mimeType);
$fileMetadata->setMimeType($mimeType);

$driveService->files->create($fileMetadata, [
‘data’ => file_get_contents($filePath),
‘mimeType’ => $mimeType,
‘uploadType’ => ‘multipart’,
‘fields’ => ‘id’
]);
}

header(‘Location:’ . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
}

break;

case ‘delete’:

if (isset($_GET[‘fid’])) {
$driveService->files->delete(htmlspecialchars($_GET[‘fid’]));
header(‘Location:’ . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

break;
}
}
ob_end_flush();

/** Функции */

function printTree($tree)
{
if (!is_null($tree) && count($tree) > 0) {
echo ‘<ul>’;
foreach ($tree as $kn => $node) {
echo ‘<li>’;
echo ‘<img src=»‘.$node[‘iconLink’].'» alt=»»>’;
echo ‘<a href=»‘.$node[‘webViewLink’].'»>’;

if ($node[‘mimeType’] == ‘application/vnd.google-apps.folder’){
echo ‘<b>’ . $node[‘name’] . ‘</b>’;
} else {
echo $node[‘name’];
}

echo ‘</a> ‘;
echo date(‘d.m.Y H:i:s’, strtotime($node[‘createdTime’]));

if ($node[‘mimeType’] == ‘application/vnd.google-apps.folder’){
echo ‘ <a href=»?action=newdir&pid=’.urlencode($node[‘id’]).'» title=»Новая папка»><i class=»icon-new»></i></a>’;
}
echo ‘ <a href=»?action=upload&fid=’ . urlencode($node[‘id’]) . ‘» title=»Загрузить файл(ы)»><i class=»icon-upload»></i></a>’;
echo ‘ <a href=»?action=delete&fid=’ . urlencode($node[‘id’]) . ‘» title=»Удалить файл(ы)» onclick=»return confirm(\’Вы действительно хотите удалить данный файл?\’);»><i class=»icon-delete»></i></a>’;

printTree($node[‘children’]);
echo ‘</li>’;
}
echo ‘</ul>’;
}
}

/**
* Приводим к нормальному виду глобальный массив $_FILES
*
* @param array $files
* @return array
*/
function normalizeFilesArray($files = [])
{
$result = [];

foreach ($files as $file) {
if (!is_array($file[‘name’])) {
$result[] = $file;
continue;
}

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите 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.
            Как и где взять эти значения можно найти в Интернете.

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

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

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