Простая работа с Yandex Disk API

Некоторое время назад мы уже рассматривали работу с Google Drive API на PHP.

На этот раз рассмотрим работу с Яндекс.Диск API на PHP. В этом примере я буду использовать библиотеку nixsolutions/yandex-php-library.

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

Описывать подробно процесс получения токена не стану, т.к. это выходит за рамки данной статьи. Однако, чтобы получить токен, для начала необходимо авторизироваться в Яндекс и попробовать создать новое приложение (в качестве доступа отмечаем все галочки в разделе Яндекс.Диск REST API).

Yandex Disk API

Листинг основного файла (index.php).

<?php
session_start(); // Стартуем сессии

/**
 * Описание библиотеки для работы я Яндекс-диском
 * https://github.com/nixsolutions/yandex-php-library/wiki/Yandex-Disk
 *
 * Документация по API Яндекс-диска
 * https://tech.yandex.ru/disk/doc/dg/concepts/quickstart-docpage/
 */

// Подключение автозагрузчика от Composer
require_once dirname(__FILE__) . '/vendor/autoload.php';

use Yandex\OAuth\OAuthClient;
use Yandex\OAuth\Exception\AuthRequestException;
use Yandex\Disk\DiskClient;

/**
 * Регистрация приложения
 * https://oauth.yandex.ru/client/new
 */
$settings = [
    'clientId' => '72e71c9455ef410ba4aeef934f75ff8e',     // ID приложения
    'clientSecret' => 'ef98af12eece46448c17212f73a96b11', // Никому не называть
    'callbackUrl' => 'http://' . $_SERVER ['HTTP_HOST'],   // Url переадресации
    'uriPath' => 'https://disk.yandex.ru/client/disk' // Используется для навигации по структуре диска
];

// Подключаемся к клиенту API Яндекса
$client = new OAuthClient($settings['clientId'], $settings['clientSecret']);

// Если в URL передана переменная с значением "code"
if (isset($_REQUEST['code'])) {
   // Попытка получения токена, иначе вывод ошибок
   try {
       $client->requestAccessToken($_REQUEST['code']);
   } catch (AuthRequestException $e) {
       echo $e->getMessage();
   }

   // Сохранение токена в сессию
   $_SESSION['accessToken'] = $client->getAccessToken();

   // Переадресация на главную страницу
   header('Location: ' . $settings['callbackUrl']); exit();

} elseif (!isset($_SESSION['accessToken'])) {
    $client->authRedirect(true, OAuthClient::CODE_AUTH_TYPE);
}

// Проверяем, если существует токен
if (isset($_SESSION['accessToken'])){
    $diskClient = new DiskClient($_SESSION['accessToken']);

    // Информация о пользователе
    $login = explode("\n", $diskClient->getLogin());

    // Извлекаем информацию о свободном и занятом месте
    $diskSpace = $diskClient->diskSpaceInfo();

    // Получаем информацию о содержимом диска
    $dirContent = $diskClient->directoryContents('/');

    // Если были отправлены POST-запросы
    if ($_POST){

        /**
         * Загрузка файла на диск
         */
        if (isset($_POST['upload']) && isset($_FILES['files'])){
            if ($_FILES['files']['error'][0] == 0) {
                $files = normalizeFilesArray($_FILES);

                foreach ($files as $file) {
                    $tmp = file_get_contents($file['tmp_name']);

                    $diskClient->uploadFile('/',
                        [
                            'path' => $file['tmp_name'],
                            'size' => $file['size'],
                            'name' => $file['name']
                        ]
                    );
                }

                // Переадресация на главную страницу
                header('Location: ' . $settings['callbackUrl']); exit();
            }
        }

        /**
         * Удаление выбранного файла
         */
        if (isset($_POST['delete']) && isset($_POST['delFile'])){

            $diskClient->delete($_POST['delFile']);

            // Переадресация на главную страницу
            header('Location: ' . $settings['callbackUrl']); exit();
        }

    }
}

/**
 * Нормальный вид для отображения размера файлов
 * @param $size
 * @return string
 */
function humanBytes($size)
{
    $fileSizeName = [' байт', ' Кб', ' Мб', ' Гб', ' Тб', ' Пб', ' Эб', ' Зб', ' Йб'];
    return $size ? round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . $fileSizeName[$i] : '0 байт';
}

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

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

        foreach ($file['name'] as $key => $filename) {
            $result[$key] = array(
                'name'      => $filename,
                'type'      => $file['type'][$key],
                'tmp_name'  => $file['tmp_name'][$key],
                'error'     => $file['error'][$key],
                'size'      => $file['size'][$key]
            );
        }
    }

    return $result;
}

// Подключение файла с версткой
include_once 'index.phtml';

Листинг файла с разметкой (index.phtml).

<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Яндекс-диск</title>
    <style type="text/css">
        html { height: 100%; }
        body {
            background: #fefcea linear-gradient(to top, #fefcea, #bdbdbd);
        }
        input.delete {
            border: 1px solid #fff;
            color: red;
            cursor: pointer;
        }
    </style>
</head>
<body>
<? if (isset($_SESSION['accessToken'])){?>
    <p>Вы вошли на сайт как <b><?= substr($login[1], 6) ?></b></p>

    <div>Занятое место: <b><?= humanBytes($diskSpace['usedBytes']) ?></b></div>
    <div>Свободное место: <b><?= humanBytes($diskSpace['availableBytes'] - $diskSpace['usedBytes']) ?></b> из <b><?= humanBytes($diskSpace['availableBytes']) ?></b>.</div>

    <h2>Содержимое Яндекс-диска</h2>

    <table>
        <? foreach ($dirContent as $item) {?>
            <? if ($item['displayName'] != 'disk') { // Корневую паппку не выводим ?>
            <tr>
                <td>
                    <? if ($item['resourceType'] === 'dir') { // Если является папкой ?>
                        <a href="<?= $settings['uriPath'] ?>/<?= $item['displayName'] ?>" target="_blank">[<?= $item['displayName'] ?>]</a>
                    <? } else { ?>
                         <? switch ($item['contentType']){
                            case 'image/jpeg':?>
                                <a href="https://disk.yandex.ru/client/disk?display=normal&groupBy=none&order=1&selected=/disk/<?= $item['displayName'] ?>&sort=name&view=icons&wasAsideAnimated=true&typeClustering=geo&action=null&idAlbum=undefined&selectionSource=listing&idApp=client&dialog=slider&idDialog=/disk/<?= $item['displayName'] ?>" target="_blank"><?= $item['displayName'] ?></a>
                            <? break;
                            case 'video/mp4':?>
                                <a href="https://disk.yandex.ru/client/disk?display=normal&groupBy=none&order=1&sort=name&view=icons&wasAsideAnimated=true&typeClustering=geo&action=null&idAlbum=undefined&selectionSource=listing&idApp=client&dialog=slider&idDialog=/disk/<?= $item['displayName'] ?>" target="_blank"><?= $item['displayName'] ?></a>
                            <? break;
                            default:?>
                                <?= $item['displayName'] ?>
                        <? } ?>
                    <? } ?>
                </td>
                <td>
                    <? if ($item['resourceType'] === 'file') { // Если является папкой ?>
                        <?= humanBytes($item['contentLength']) ?>
                    <? } ?>
                </td>
                <td><?= date('d.m.Y H:i:s', strtotime($item['creationDate'])) // Приводим к правильному формату времени ?></td>
                <td>
                    <form method="post">
                        <input type="hidden" name="delFile" value="<?= htmlspecialchars($item['displayName']) ?>">
                        <input type="submit" name="delete" class="delete" value="x">
                    </form>
                </td>
            </tr>
            <? } ?>
        <? } ?>
    </table>

    <h2>Загрузка файлов в Яндекс-диск</h2>
    <form method="post" enctype="multipart/form-data">
        <input type="submit" name="upload" value="Загрузить файл">
        <input type="file" name="files[]" multiple>
    </form>
<? } ?>
</body>
</html>

А вот пример того, как это будет выглядеть, если запустить скрипт.

Яндекс Диск API

Получился простой пример для работы с АПИ Яндекс диска. Пример довольно старый, но вполне рабочий. Для работы диска лучше завести свои токены (в статье используются тестовые токены, которые могут со временем перестать работать).

Для удобства закачал исходники на Github. Не забудьте выполнить команду в консоле $ composer install.

Спасибо за внимание и до новых встреч.

Полезные материалы:

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

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

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

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