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




Встала задача где-то хранить кучу фотографий для сайта и других файлов. Покупать выделенный сервер для небольшого сайта, и тратить 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, 17:02    Павел Карелин   
4    1229 +5

Комментарии (18)

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

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

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

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

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

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

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

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

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


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

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