Разрабатываем мы тут один проект, для реализации которого сразу было понятно, что надо будет использовать Dropbox. Суть в том, чтобы в одном месте синхронизировать рабочие файлы различных сотрудников, каждый из которых работает на своем локальном компьютере и как бы не подключен к какому-то единому серверу. А дальше уже эти файлы затягивать на сервер, обрабатывать, превращать в нужные сущности и в личном кабинете конечные клиенты могли бы получать доступ к преобразованной информации, чтобы распечатать или отправить себе на почту в виде PDF-файла (ну, это в общих чертах).
Итак, главная здесь задача — это работать с Dropbox посредством API. Честно сказать, я думал все будет намного проще, ибо я и ранее в сети видел упоминания о Dropbox MediaSource for MODX, и одно из них на странице Марка Хамстра. Но установив этот пакет при попытке просмотреть список файлов в полученном источнике файлов все, что я увидел — фатальная ошибка выполнения скрипта. Вообще пакет написан в 2012-ом году, так что он может быть просто не актуален. Забегая вперед, скажу, что этот пакет я в последствии перепишу и заставлю таки нормально работать, но это уже позже. Есть еще профильная статья на modx.pro, но это работа shell-командами, а меня интересует именно взаимодействие средствами PHP, то есть в целом эта статья мне тоже никак не помогла, во всяком случае в текущем вопросе. В общем, в этой же статье я просто опишу много того, с чем столкнулся и чего нового узнал/освоил. Она будет объемная, но и полезной информации тоже много.
Кстати, здесь и далее я буду писать только о том, что сам пробовал и какие результаты получил. В действительности же функционал в разы больше, чем мы здесь рассматриваем, так как только типов API у Dropbox несколько. На этот счет приглянулась вот эта статья.
Создание API-приложения
Для того, чтобы к вашему dropbox-у появился какой-то доступ извне, надо создать приложение (само собой разумеется, что вы для начала должны зарегистрироваться в Dropbox). Для этого идем на страничку www.dropbox.com/developers/apps и жмем Create app (Кстати, название приложения должно быть уникальное для всего Dropbox-а (так как есть возможность публиковать публичные приложения, так что лучше указывать домен сайта или типа того, ибо названия типа myApp и т.п. заняты и дропбокс не даст сохранить)). Типов создаваемых приложений два Drop-ins app и Dropbox API app, мы будем создавать второй.
?
Здесь сразу же подробней рассмотрим шаг 3.
Can your app be limited to its own folder?
Если выбрать «My app only needs access to files it creates.», то для приложения будет создана собственная папка, куда и будет доступ у приложения. У меня это папка Приложения/[AppName]. То есть папка Приложения — это системная для всех приложений, а далее для каждого приложения создается своя папка.
А если выбрать «My app needs access to files already on Dropbox.», то приложение получит доступ к корневой папке и далее список доступных файлов будет ограничиваться только выбранными типами файлов. То есть если вы выбираете этот пункт, то появляется новый шаг What type of files does your app need access to? и там вы можете выбрать или «All file types» (то есть все файлы) или «Specific file types» и указать какие типы файлов доступны.
?
После того, как мы нажали «Create App», приложение будет создано и нам открывается страница настроек приложения. На ней мы кроме всего прочего найдем App key и App secret, но они нам пока не понадобятся, их использование мы рассмотрим позже. А пока нас интересует Access token. Сгенерируем его и скопипастим куда-нибудь в недоступное место. Повторно его не получится увидеть. Правда можно сгенерировать новый токен, и что интересно — работать будут и предшествующие. Я сгенерил три токена и все они работают, при чем я не могу увидеть список используемых токенов и отменить не нужные, могу только удалить все приложение. Катца не секурно немного, но это скорее фича нежели бага.
?
Выполнение основных запросов.
Все, access token у нас есть, можно выполнять простейшие запросы. Здесь нам в помощь оффдокументация по CORE API for PHP. Для начала качаем PHP SDK (я качал v.1.1.4) (Git-проект). Заливайте куда-нибудь в корень сайта, так как в дальнейшем мы рассмотрим примеры, требующие доступ к экзамплам извне. А так примеры мы будем выполнять в консоли.
Информация о профиле.
Для начала получим информацию о профиле:
<?php
ini_set('display_errors', 1);
print '<pre>';
# Include the Dropbox SDK libraries
require_once MODX_BASE_PATH . "dropbox/lib/Dropbox/autoload.php";
use \Dropbox as dbx;
$accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Здесь ваш Access token
$dbxClient = new dbx\Client($accessToken, "PHP-Example/1.0");
$accountInfo = $dbxClient->getAccountInfo();
print_r($accountInfo);
В ответ вы должны увидеть что-то типа такого:
Array
(
[referral_link] => https://db.tt/xxxxx
[display_name] => Nikolay Lanets
[uid] => 123456789
[email_verified] => 1
[team] =>
[quota_info] => Array
(
[datastores] => 0
[shared] => 24229
[quota] => 2415919104
[normal] => 458685614
)
[country] => RU
[email] => info@local.host
)
Если видите, значит все работает :)
Запись файла.
Лучше сразу начинать с записи файла, так как если сразу не понятно четко где реально корневая папка приложения, получая пустой список при попытке чтения директории начинаешь терять время где же что не так.
Чтобы записать файл в дропбокс, надо указать путь до локального файла и указать путь и имя для заливаемого файла (может отличаться). Например:
<?php
ini_set('display_errors', 1);
print '<pre>';
# Include the Dropbox SDK libraries
require_once MODX_BASE_PATH . "dropbox/lib/Dropbox/autoload.php";
use \Dropbox as dbx;
$accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$dbxClient = new dbx\Client($accessToken, "PHP-Example/1.0");
$f = fopen(MODX_BASE_PATH . "robots.txt", "rb");
$fileMetadata = $dbxClient->uploadFile("/robots4.txt", dbx\WriteMode::add(), $f);
fclose($f);
print_r($fileMetadata);
Array
(
[revision] => 66056
[bytes] => 25
[thumb_exists] =>
[rev] => 10208031c0d71
[modified] => Wed, 03 Dec 2014 20:37:35 +0000
[mime_type] => text/plain
[path] => /robots4.txt
[is_dir] =>
[size] => 25 bytes
[root] => dropbox
[client_mtime] => Wed, 03 Dec 2014 20:37:35 +0000
[icon] => page_white_text
)
Запись сделана, файл можно обнаружить в папке дропбокса (если у приложения OwnFolderOnly-права, то файл точно не будет в корневой папке, смотрите в Приложения/[AppName]).
Содержимое папки.
<?php
ini_set('display_errors', 1);
print '<pre>';
# Include the Dropbox SDK libraries
require_once MODX_BASE_PATH . "dropbox/lib/Dropbox/autoload.php";
use \Dropbox as dbx;
$accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$dbxClient = new dbx\Client($accessToken, "PHP-Example/1.0");
$folderMetadata = $dbxClient->getMetadataWithChildren("/");
print_r($folderMetadata);
Array
(
[hash] => fe7f3531dac71e5df7d1be97d2b8e3e3
[thumb_exists] =>
[bytes] => 0
[path] => /
[is_dir] => 1
[icon] => folder
[root] => dropbox
[contents] => Array
(
[0] => Array
(
[bytes] => 0
[rev] => b74031c0d71
[revision] => 2932
[icon] => folder
[path] => /Programs
[is_dir] => 1
[thumb_exists] =>
[root] => dropbox
[modified] => Thu, 15 Dec 2011 18:24:59 +0000
[size] => 0 bytes
)
)
[size] => 0 bytes
)
Чтение файла.
<?php
ini_set('display_errors', 1);
print '<pre>';
# Include the Dropbox SDK libraries
require_once MODX_BASE_PATH . "dropbox/lib/Dropbox/autoload.php";
use \Dropbox as dbx;
$accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$dbxClient = new dbx\Client($accessToken, "PHP-Example/1.0");
$f = fopen(MODX_BASE_PATH . "robots2.txt", "w+b");
$fileMetadata = $dbxClient->getFile("/robots4.txt", $f);
fclose($f);
print_r($fileMetadata);
Array
(
[rev] => 10208031c0d71
[thumb_exists] =>
[path] => /robots4.txt
[is_dir] =>
[client_mtime] => Wed, 03 Dec 2014 20:37:35 +0000
[icon] => page_white_text
[bytes] => 25
[modified] => Wed, 03 Dec 2014 20:37:35 +0000
[size] => 25 bytes
[root] => dropbox
[mime_type] => text/plain
[revision] => 66056
)
Вот минимальный набор функций для работы с Dropbox. А вот дальше будет гораздо сложнее…
Файловый менеджер Dropbox на вашем сайте.
В примерах, имеющихся в скаченном SDK, есть вот такой файл: examples/web-file-browser.php. Вот его мы и будем мучить… Сразу советую первой строчкой дописать ini_set('display_errors', 1); Далее пойдем по порядку по мере столкновения с проблемами.
Настройка web-file-browser.app
При заходе на страничку (у меня это dropbox/examples/web-file-browser.php), мы получаем следующую ошибку:
Fatal error: Uncaught exception 'Exception' with message 'Unable to load "...../dropbox/examples/web-file-browser.app": File doesn't exist: "...../dropbox/examples/web-file-browser.app"' бла-бла-бла
Суть в том, что приложение пытается получить файл с ключами. Необходимо создать этот файл, в который в JSON-формате записываем app-ключи:
{
"key": "INSERT_APP_KEY_HERE",
"secret": "INSERT_SECRET_HERE"
}
Эти ключи вы найдете на страничке управления своим приложением.
?
Создаем указанный файл и если все ОК, получаем следующую ошибку, уже более симпатичную)) *Сарказм*
?
Для нас здесь две печали: маленькая и большая. Маленькая — это «Invalid redirect_uri:....». Надо просто добавить указанный УРЛ в настройке приложения. А большая — это 'only localhost URIs can start with «http://»; all others must start with «https://»'. То есть если у вас на сайте не используется протокол https, то вы просто не сможете использовать этот функционал. Так что придется поднимать https.
Настройка HTTPS (SSL).
Если у вас shared-хостинг или типа того, то проще всего обратиться в службу поддержки хостинга, но это совсем не гарантирует вам решения. Почему? Не все так просто там с этими сертификатами, в том числе в плане нескольких сертификатов на один ip. Мы сидим на digitalocean.com на облачных серверах, так что сервер в нашем распоряжении и будем настраивать SSL самостоятельно. Кстати, в этом плане опять-таки сильно радует DO, ибо есть отличные статьи по настройке SSL и на nginx, и на apache. У нас используется связка nginx+apache, так что сертификат мы создаем только один раз и в настройках этих серверов указываем путь до единого сертификата.
Чтобы сгенерить сертификат выполняем:
sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
Вот когда вы выполняете третью команду, надо будет пошагово ответить на несколько ответов, и в итоге у вас будет карточка типа
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
Organizational Unit Name (eg, section) []:Ministry of Water Slides
Common Name (e.g. server FQDN or YOUR name) []:your_domain.com
Email Address []:admin@your_domain.com
Вообще читайте те статьи, там все подробно расписано. Один только момент: как я и говорил, если у вас связка nginx+apache, то при конфигурации апача не надо повторно создавать сертификат, а надо просто в конфигурации прописать путь до созданного уже сертификата. Но с апачем будьте внимательней, там не все так просто (читайте статью). Во-первых, надо активировать мод SSL.
sudo a2enmod ssl
sudo service apache2 restart
Во-вторых, после настройки виртдомена активировать защищенный домен и пестартануть апач.
sudo a2ensite default-ssl
sudo service apache2 restart
Вот здесь (или на первом рестарте) у меня вылезла логичная ошибка — конфликт портов. 443 порт (default SSL) у меня уже был занят nginx-ом, поэтому апачу пришлось указать другой порт (к примеру, 4444). Для этого не только для хоста указывается этот порт, но и в apache2/ports.conf правится
<IfModule mod_ssl.c>
# If you add NameVirtualHost *:443 here, you will also have to change
# the VirtualHost statement in /etc/apache2/sites-available/default-ssl
# to <VirtualHost *:443>
# Server Name Indication for SSL named virtual hosts is currently not
# supported by MSIE on Windows XP.
Listen 4444
</IfModule>
<IfModule mod_gnutls.c>
Listen 4444
</IfModule>
Если рестарт апача прошел успешно, то ваш сайт должен быть доступен по адресу domain/ или domain:4444/ (я не буду сейчас очень сильно углубляться в это дело, просто вот для заметки написал).
И, если вы захотите обзавестись трастовым сертификатом, да еще и на холяву, советую к прочтению. Я себе оформил, жду :)
Если вы все настроили верно (в том числе в настройках приложения указали верный коллбэк-УРЛ), то вы увидите предложение авторизоваться и присоединиться к вашему приложению.
?
Конечно тут все без оформления, и буковки русские он не очень понимает, но это же сэмпл, и главное — механизм общий работает, и даже можно скачивать и загружать файлы прям через эту морду, так что в целом задача решена. Ну и возможно в этом будет полезен этот раздел: www.dropbox.com/developers/dropins