Применение для Яндекс.Диска



Встала задача где-то хранить кучу фотографий для сайта и других файлов. Покупать выделенный сервер для небольшого сайта, и тратить 5-10 тысяч рублей, совсем не разумно. Тут мне на глаза попался Яндекс.Диск, вместилище на 1тб тут стоит всего лишь 200 рублей. И я подумал, а почему бы и нет? Поковырял API, нашел симпатичную библиотеку yandex-php-library и на её основе сворганил свой набор скриптов для любимой MODX REVO. В итоге все работает в связке с pdoTools. Посмотреть как работает можно тут.

Как мне кажется идея достаточно не плохая. Пока все простенько, и недоработано, но уже прекрасно работает. Остается только получить токен и все, способ его получения хорошо описан в yandex-php-library. Для самых хитрых показываю код. Сразу скажу, в коде много не логичностей и откровенных ляпов, так как писал на скорую руку.

Сниппет getFileYandexDisc работает в паре с pdoPage
<?php
require_once MODX_CORE_PATH.'/components/yandexdisc/custom/yandex/vendor/autoload.php'; // Подключаем библиотеку yandex-php-library
require_once MODX_CORE_PATH.'/components/yandexdisc/model/yandexDisc.class.php'; // Я уже создал обертку для Yandex\Disk\DiskClient, но вы можете и не создавать её

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

$yandexDisc = new yandexDisc('Тут ваш токен, полученный через OAuth');
$yandexDisc->setServiceScheme(yandexDisc::HTTPS_SCHEME);

$dirContent = $yandexDisc->directoryContents('/elenamart/Album1/');

$arrayFiles = array();

if(empty($offset)){
   $offset = 0; 
}
if(empty($limit)){
   $limit = 10; 
}

$s = 0;
$output = '';
foreach ($dirContent as $podDirItem) {
    if($podDirItem['href'] != '/elenamart/Album1/'){
        $arrayFile[] = $podDirItem;
        $itog = $offset + $limit;
        if($s >= $offset AND $s < $itog){
           $output .=  $modx->parseChunk($tplRow, array('href' => $podDirItem['href']));; 
        }
        
        $s++;
    }
}
$count = count($arrayFile);
$modx->setPlaceholder('page.total', $count);

return $output;

Будущая обертка для Yandex\Disk\DiskClient
<?php
use Yandex\Disk\DiskClient;

class yandexDisc extends Yandex\Disk\DiskClient{

    var $diskClient;
    var $modx;

    // Получаем список файлов
    function getListFiles(){

    }

    // Получаем содержимое файла
    function getFileContent(){

    }
}

Файл для отрисовки изображения
<?php
define('MODX_API_MODE', true);
require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/index.php';

require_once MODX_CORE_PATH.'/components/yandexdisc/custom/yandex/vendor/autoload.php'; // Подключаем библиотеку yandex-php-library
require_once MODX_CORE_PATH.'/components/yandexdisc/model/yandexDisc.class.php'; // Я уже создал обертку для Yandex\Disk\DiskClient, но вы можете и не создавать её

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

$yandexDisc = new yandexDisc('Токен вашего диска');
$yandexDisc->setServiceScheme(yandexDisc::HTTPS_SCHEME);

$size = 'XXXL';

if(isset($_GET['size'])){
    $size = $_GET['size'];
}

if(isset($_GET['target'])){
    $target = $_GET['target'];

    $file = $yandexDisc->getImagePreview($target, $size);

    header('Content-Description: File Transfer');
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Content-Type: '.$file['headers']['content-type']);
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Date: ' . $file['headers']['date']);
    header('Content-Length: ' . $file['headers']['content-length']);
    header('Accept-Ranges: ' . $file['headers']['accept-ranges']);
    echo $file['body'];
}

Вызываем сниппет getFileYandexDisc с пагинацией
[[!pdoPage?
    &limit=`12`
    &parents=`0`
    &element=`getFileYandexDisc`
    &tplRow=`portfolioRow`
]]
[[!+page.nav]]

Код чанка
<img src="/assets/components/yandexdisc/echoFile.php?target=[[+href]]&size=350x350" alt="">
PS: если сообществу интересно, то могу доработать расширение и залить на modstore, за сравнительно небольшую цену. Если кому то интересно и кто то приобрел пишите в комментариях.

SDK для работы с api Яндекс.Диск тут.
Оригинал статьи тут.
Павел Карелин
14 марта 2017, 14:02
modx.pro
6
6 213
+5

Комментарии: 18

Василий Наумкин
14 марта 2017, 17:07
+1
Прикольно! Только нужно сразу предупредить, что это отдача сайтов через PHP, а не прямые ссылки на картинки, как у Selectel или S3 Cloud Storage.

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

Ну и не совсем понятно, насколько хорошо эти картинки будут кэшироваться, хоть я и вижу соотвествующие заголовки. Может, есть где-то демосайт погонять?
    Павел Карелин
    14 марта 2017, 17:08
    0
    Да в сравнение с выделенным сервером конечно ни как не идет, но и ценовая разница колосальная. В основном был упор на то что яндекс диском действительно удобно пользоватся. Посмотреть можно тут elenamart.ru/portfolio.html, внизу есть счетчик. Это так сказать пробное дело, в принципе можно подключить и кеширование, что бы работало пошустрее.
      Василий Наумкин
      14 марта 2017, 17:12
      0
      Ну вот, печалька — сейчас браузер не кэширует картинки, а если бы и кэшировал, то PHP всё равно отрабатывает каждый раз и страница генерируется по 0.5 сек.

      А если делать кэш на HDD сервера — то какой смысл выносить картинки в Яндекс? В общем, идея интересная, но для реального применения скорости будет маловато.
        Павел Карелин
        14 марта 2017, 17:15
        0
        Можно реализовать асинхронную загрузку и страница будет работать быстрее. 0.5 не так уж и много в принципе, например меня вполне устраивает. По сути я получаю при генерации страницы просто урлы изображений. И вот именно урлы можно кешить. И по ним уже запрашивать изображения. А сами изображения генерируются уже напрямую. Вот например я включил кеширование, урлов и теперь страница отдается 0.0135 s. При чем фотки не кешатся, а берутся напрямую. То есть это вполне реально настроить было бы желание.
          Василий Наумкин
          14 марта 2017, 17:28
          +1
          echo $file['body'];
          Это не ссылка — это именно что тело документа, которое ты грузишь с Яндекса и выдаёшь пользователю через API.

          Я просто пытаюсь объяснить, что это сейчас страница генерируется 0.5 сек, для одного пользователя. Если же их будет больше, то эта цифра вырастет. Ну а если кто-то даст ссылку на твой сайт на Хабре или Реддите, то будет очень много запросов и Яндекс наверняка отключит тебе доступ на некоторое время.

          Неспроста у них нет прямых ссылок на файлы.

          и теперь страница отдается 0.0135 s.
          А вот это уже гораздо лучше!

          Правда дальше всё равно файлы опять отдаются через отдельный скрипт echoFile.php, но на загрузку самой страницы оно не влияет.
            Павел Карелин
            14 марта 2017, 17:44
            0
            Да согласен, можно попробовать в принципе поискать аналог и подключится к нему. Просто сама идея достаточно удобная.
              Воеводский Михаил
              14 марта 2017, 17:53
              +2
              Идея хороша для случаев, когда заведомо известно, что хранить необходимо много, а доступ будет очень ограниченный. Например, фотоархив, свой для каждого пользователя. При этом, есть возможность хранить 50-100 Гб кэша в течение 2-3 дней на случай повторного интереса пользователя к просмотренным фотографиям.
                Павел Карелин
                14 марта 2017, 17:55
                0
                Я делал специально для сайта фотографа, там вряд-ли будет большая посещаемость, только изредка будут заходить заказчики что бы посмотреть свои фото. Понятно что для сайта с большой посещаемостью решение не годится.
                Воеводский Михаил
                14 марта 2017, 17:54
                +1
                То есть, для архивов с ограниченным доступом — ЯД, для публичных файлов — облачные хранилища с прямыми ссылками.
                Денис
                14 марта 2017, 18:16
                0
                Василий верно сказал про отключение доступа к диску из-за большого количества запросов. На одном проекте использовал этот Драйвер для Media Source для работы с Яндекс.Диск. Оказалось, что использование диска, в качестве удаленного файлового хранилища нерентабельно из-за большой нагрузки, после которой яндекс переставал отдавать файлы(огромное количество изображений на страницах). Стали использовать яндекс.диск в качестве файлопомойки с которой импортировали нужные нам файлы.
            Sergey Leleko
            14 марта 2017, 18:56
            0
            Хе, забавно, на некоторых фото знакомый человек)
            Павел Карелин
            14 марта 2017, 18:58
            0
            Василий, а гугл диск выдает прямые ссылки, не знаешь. Или там такая же беда будет с ограничением?
            Вот пример картинки.
              Василий Наумкин
              14 марта 2017, 19:31
              0
              Не знаю.

              Посмотрим, если эта картинка тут провисит неделю — значит всё ок, прямые ссылки работают. Но, опять же, нужно проверить ограничения API.
                Alexander
                14 марта 2017, 20:51
                0


                Эта картинка с гуглфоток с октября не умирает — проверяю раз в месяц, примерно.
                  Василий Наумкин
                  14 марта 2017, 20:53
                  0
                  Круто.

                  Осталось теперь по лимитам протестировать.
                    Alexander
                    14 марта 2017, 21:04
                    0
                    Скриптом через разные прокси?
                    Если есть желание можно на этой картинке потестировать.
            Дмитрий Павлов
            14 марта 2017, 21:41
            0
            А Flickr не подойдет для этих целей? API имеется…
              Petro
              15 марта 2017, 16:27
              0
              Можно. Есть и библиотека phpFlickr для этого. Правда результат лучше поместить в кэш
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              18