7.17. Работа с содержимым хранилища через API

Примечания:

  • Инструкция описывает API для работы с содержимым хранилища. Для работы с самим хранилищем используйте общее API.
  • Лимиты на количество запросов: в старой версии API идентичны лимитам общего API, в новой версии API таких ограничений нет (можно отправлять больше запросов).
  • Во всех методах поддерживаются только полные пути, без ...

Для отправки запросов используйте ваш адрес хранилища.

Получение токена:

  1. Создайте пользователя веб-интерфейса (если не создан).
  2. Авторизуйтесь с помощью логина и пароля созданного пользователя и получите токен.

Далее используйте полученный токен при работе с остальными методами (токен указывается в заголовке Authorization: Bearer).

Авторизация и загрузка файла в хранилище:

<?php

// Адрес хоста хранилища, выводится вверху раздела в панели управления
$host = 'example.cdn.express';

// Файл, который нужно загрузить в хранилище
$file = '/path/to/local/file.ext';

// Путь для загрузки в хранилище и исходное имя файла
$path = '/upload/dir/' . basename($file);

// Логин пользователя веб-доступа к хранилищу (данные можно получить в панели управления на вкладке "Пользователи и API")
$login = 'storage_login';

// Пароль пользователя веб-доступа к хранилищу
$password = 'storage_password';

$curl = curl_init();

// Авторизация
curl_setopt($curl, CURLOPT_URL, 'https://' . $host . '/~/api/auth');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLOPT_POSTFIELDS, ['login' => $login, 'password' => $password]);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data']);
$json = curl_exec($curl);
$token = json_decode($json, true)['data']['token'];
if (!empty($token)) {
    echo 'Authenticated successfully' . PHP_EOL;
} else {
    // Проверьте правильность указания хоста, логина и пароля
    echo 'Authentication failed. Check host, login and password.' . PHP_EOL;
    exit;
}

// Загрузка файла (если файл уже существует в хранилище, будет ошибка)
echo 'Uploading ' . $file . ' ... ';
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_URL, 'https://' . $host . '/~/api/file?path=' . urlencode($path));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_INFILE, fopen($file, 'rb'));
curl_setopt($curl, CURLOPT_INFILESIZE, filesize($file));
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $token]);
var_dump(curl_exec($curl));
$success = curl_getinfo($curl)['http_code'] === 200;
if ($success) {
    echo 'success.' . PHP_EOL;
} else {
    echo 'failed.' . PHP_EOL;
}
curl_close($curl);

Методы для работы с токенами.

Важные моменты:

  • Для использования всех методов в момент авторизации у пользователя должно быть установлено право на запись. Без этого права будет доступно только получение списка файлов и скачивание.
  • При любом изменении прав пользователя нужно авторизоваться заново и получать новый токен.

PUT /~/api/auth

Параметры в теле запроса:
multipart/form-data

  • login — логин пользователя веб-доступа.
  • password — пароль пользователя веб-доступа.
  • remember — срок действия токена:
    • 0 — 6 часов (значение по умолчанию).
    • 1 — 7 дней.

Авторизует под указанным пользователем и возвращает токен со сроком действия.

Ответ:

  • token — токен для использования в заголовке Authorization: Bearer при работе с остальными методами.
  • till — временная метка окончания срока действия токена.

DELETE /~/api/auth

Токен передаётся в заголовке (как в остальных методах).

Деактивирует полученный ранее токен.

Методы для работы с каталогами и получения их содержимого.

GET /~/api/directory

Параметры запроса:

  • path — путь к каталогу, содержимое которого нужно получить (в одном запросе можно указывать несколько параметров path — данные будут возвращаться по уникальным значениям с сортировкой по длине пути в сторону увеличения).
  • recursive (необязательный) — рекурсивное получение данных:
    • 0 — получить содержимое только указанного каталога (значение по умолчанию).
    • 1 — получить содержимое указанного каталога и всех его подкаталогов.
  • iterator (необязательный) — получение данных в специальном формате, когда вместо одного большого JSON ответ содержит строки с отдельными JSON для каждого элемента каталога. Это позволяет существенно экономить оперативную память при обработке содержимого каталогов с большим количеством элементов — можно просматривать ответ построчно, находить JSON только нужного элемента и распаковать его без необходимости распаковки большого JSON со всеми элементами.
    • 0 — получить ответ в виде одного большого JSON (значение по умолчанию).
    • 1 — получить ответ в виде строк с отдельными JSON.

Ответ содержит список объектов с информацией по каждому из них:

  • name — имя файла или каталога.
  • path — путь к объекту от корня хранилища.
  • isDirectory — тип объекта: каталог или нет.
  • size — размер файла в байтах (для каталогов всегда 4096).
  • mtime — временная метка последнего изменения содержимого объекта.
  • ctime — временная метка последнего изменения метаданных объекта.
  • birthtime — временная метка создания или загрузки объекта.
  • media — тип медиа (для медиафайлов).
  • ext — расширение (для файлов с расширением).
  • share — информация о наличии публичной ссылки: ID публичной ссылки или null (при нескольких параметрах path или рекурсивном получении данных всегда null).
  • uri — URI файла в зависимости от статуса публичного доступа:
    • Публичный доступ включён — прямая ссылка.
    • Публичный доступ отключён — защищённая ссылка (начинается с /~/secure/).

PUT /~/api/directory

Параметры в теле запроса:
multipart/form-data

  • path — путь к новому каталогу.

Создаёт новый каталог по указанному пути.

POST /~/api/directory

Параметры в теле запроса:
multipart/form-data

  • path — путь к каталогу, который нужно переименовать или переместить.
  • dest — новый путь или название каталога (путь должен существовать).
  • overwrite — режим перезаписи, если целевой каталог уже существует:
    • 0 — не перезаписывать и возвращать ошибку (значение по умолчанию).
    • 1 — заменять содержимое существующего каталога.

Переименовывает или перемещает указанный каталог.

DELETE /~/api/directory

Параметры запроса:

  • path — путь к каталогу, который нужно удалить.

Удаляет указанный каталог со всем содержимым. Родительские каталоги не затрагиваются.

Методы для работы с файлами.

Примечания:

  • Максимальный размер загружаемого файла — 50 ГБ. При попытке загрузить файл большего размера сервер вернёт «413 Request Entity Too Large».
  • По количеству и объёму загруженных данных доступна статистика.

PUT /~/api/file

Параметры запроса:

  • path — путь для загрузки с именем файла.
  • overwrite — режим перезаписи, если целевой файл уже существует:
    • 0 — не перезаписывать и возвращать ошибку (значение по умолчанию).
    • 1 — заменять существующий файл.

Загружает файл по указанному пути (от корня хранилища).

Пример кода на PHP см. в начале статьи.

Команда для загрузки файла из консоли:

curl -X PUT 'https://example.cdn.express/~/api/file' --header 'Authorization: Bearer <token>' --data-binary '@/path/to/local/file.ext' --url-query 'path=/upload/dir/file.ext'

Для обеспечения максимальной скорости файлы скачиваются не через метод, а с помощью GET-запроса по прямой или защищённой ссылке на файл.

  1. Получите список файлов каталога, в котором находится файл, который нужно скачать.
  2. Из списка получите URI нужного файла.
  3. Отправьте GET-запрос на адрес хранилища с полученным URI.

PUT /~/api/archive

Параметры в теле запроса:
application/json

  • items — пути к файлам и каталогам, которые нужно скачать.

Скачивает перечисленные объекты в виде архива в формате .zip (все объекты должны существовать).

HEAD /~/api/file

Параметры запроса:

  • path — путь к файлу или каталогу, существование которого нужно проверить.

Проверяет существование файла или каталога по указанному пути: ответ 200 — существует, ответ 404 — не существует.

POST /~/api/file

Параметры в теле запроса:
multipart/form-data

  • path — путь к файлу, который нужно переименовать или переместить.
  • dest — новый путь или имя файла (путь должен существовать).
  • overwrite — режим перезаписи, если целевой файл уже существует:
    • 0 — не перезаписывать и возвращать ошибку (значение по умолчанию).
    • 1 — заменять существующий файл.

Переименовывает или перемещает указанный файл.

DELETE /~/api/file

Параметры запроса:

  • path — путь к файлу, который нужно удалить.

Удаляет указанный файл. Родительские каталоги не затрагиваются.

Методы для работы с публичными ссылками.

PUT /~/api/share

Параметры запроса:

  • path — путь к файлу или каталогу, для которого нужно создать публичную ссылку.
  • write — статус доступа к изменению содержимого каталога: 1 (доступ разрешён) или 0 (доступ запрещён).
  • deathtime (необязательный) — временная метка автоматического удаления ссылки (должна быть больше текущей даты, 0 — не удалять).

Создаёт публичную ссылку для указанного объекта.

Ответ:

  • id — ID публичной ссылки.
  • path — путь к объекту публичной ссылки.
  • birthtime — временная метка создания публичной ссылки.
  • isDirectory — тип объекта: каталог или нет.
  • exists — существование объекта публичной ссылки (при создании всегда true).
  • deathtime — временная метка автоматического удаления ссылки (если передавалась в запросе) или 0.
  • writeAccess — статус доступа к изменению содержимого каталога (по умолчанию всегда false, настраивается отдельным методом),
  • uri — URI публичной ссылки (начинается с /~/share/).

GET /~/api/share

Параметры запроса:

  • id (необязательный) — ID публичной ссылки, по которой нужно получить данные.

Возвращает список публичных ссылок и их данные. Если указан ID публичной ссылки — возвращает данные только этой ссылки.

Ответ содержит список ссылок с информацией по каждой из них (или информацию по конкретной ссылке, если запрос был с указанием ID):

  • id — ID публичной ссылки.
  • path — путь к объекту публичной ссылки.
  • isDirectory — тип объекта: каталог или нет.
  • writeAccess — статус доступа к изменению содержимого каталога (по умолчанию всегда false, настраивается отдельным методом),
  • birthtime — временная метка создания публичной ссылки.
  • deathtime — временная метка автоматического удаления ссылки (если передавалась в запросе) или 0.
  • exists — существование объекта публичной ссылки (если файл или каталог были переименованы, перемещены или удалены, будет false).
  • uri — URI публичной ссылки (начинается с /~/share/).

POST /~/api/share

Параметры запроса:

  • id — ID публичной ссылки, для которой нужно изменить права доступа (только для ссылок на каталоги).

Параметры в теле запроса:
multipart/form-data

  • write — статус доступа к изменению содержимого каталога: 1 (доступ разрешён) или 0 (доступ запрещён).

Устанавливает для публичной ссылки права доступа к изменению содержимого каталога.

Ответ аналогичен получению списка ссылок.

DELETE /~/api/share

Параметры запроса:

  • id — ID публичной ссылки, которую нужно удалить.

Удаляет публичную ссылку с указанным ID. Объект, на который указывала ссылка, не затрагивается.

Внимание!

Обновление секретного ключа выполняется через панель управления или общее API

GET /~/api/link

Параметры запроса:

  • path — путь к файлу от корня хранилища.
  • time (необязательный) — временная метка окончания жизни ссылки (должна быть больше текущей даты).
  • ip (необязательный) — IP-адрес, которому будет разрешён доступ к файлу по ссылке.

Генерирует и возвращает Secure Link для указанного файла с заданными параметрами.

Ответ:

  • token — закодированный хеш совокупности данных секретного ключа, пути и параметров.
  • uri — URI ссылки (начинается с /secure/).
  • url — полная ссылка.
  • params:
    • ip — IP-адрес, для которого разрешён доступ к файлу по ссылки (если передавался в запросе).
    • time — временная метка окончания жизни ссылки (если передавалась в запросе).
    • path — путь к файлу от корня хранилища.
  • stat:
    • size — размер файла, на который указывает ссылка (в байтах).
    • atimeMs — временная метка последнего доступа к файлу (в миллисекундах).
    • mtimeMs — временная метка последнего изменения содержимого файла (в миллисекундах).
    • ctimeMs — временная метка последнего изменения метаданных файла (в миллисекундах).
    • birthtimeMs — временная метка создания файла (в миллисекундах).
  • 200 — запрос выполнен успешно.
  • 400 — ошибка при выполнении запроса.
    • В теле ответа будет описание ошибки, например «File exists», если загружаемый файл уже существует, или «Item not found», если не найден ID публичной ссылки.
  • 401 — не выполнена авторизация.
    • В теле ответа будет либо «Invalid credential 'login' or 'password'», если ошибка возникла во время авторизации, либо «Unauthorized» во всех остальных случаях.
  • 403 — доступ заблокирован.
  • 404 — указанный в запросе файл или путь не существует.
  • 429 — слишком много запросов.
  • 502/503 — нужно подождать перед отправкой следующего запроса.
    • Например, запрос попал на момент перезапуска API или сервер был нагружен и не успел обработать запрос.

В зависимости от статуса авторизации и типа запроса ответы API содержат дополнительные заголовки.

Для всех запросов:

  • x-storage-name — название или псевдоним хранилища (если установлен).
  • x-storage-logo — логотип из настроек хранилища: если установлен — URL файла логотипа (домен cdn.adm.tools).
  • x-storage-mode — статус вида при открытии в настройках хранилища: list (список) или table (галерея).

Для запросов с авторизацией:

  • x-user-login — логин пользователя веб-доступа.
  • x-user-write — право на запись пользователя веб-доступа: 1 (есть доступ) или 0 (нет доступа).
  • x-user-till — временная метка окончания срока действия токена.

Для запросов проверки существования и скачивания:

  • x-stat-directory — тип объекта: каталог или нет.
  • x-stat-mtime — временная метка последнего изменения содержимого объекта.
  • x-stat-ctime — временная метка последнего изменения метаданных объекта.
  • x-stat-birthtime — временная метка создания или загрузки объекта.
  • x-stat-size — размер файла в байтах (для каталогов всегда 4096).
Postman — приложение для тестирования API.

Подготовка к работе с Postman:

  1. Импорт файлов коллекции и окружения:
    1. Скачайте файлы:
    2. В главном меню выберите «File → Import» (или нажмите Ctrl+O), выберите скачанные файлы и импортируйте их.
  2. Настройте окружение:
    1. В левой панели выберите «Environments».
    2. В списке окружений выберите «storage».
    3. В колонке «Current value» укажите свои данные и нажмите «Save»:
      • domain — адрес вашего хранилища.
      • username — имя пользователя хранилища.
      • password — пароль пользователя хранилища.
    4. В правом верхнем углу выберите «storage».

Авторизация:

  1. В левой панели выберите «Collections».
  2. В списке коллекций разверните «storage» и выберите метод «authorization».
  3. Нажмите «Send» — метод вернёт токен и Postman автоматически подставит токен в окружение.

Далее можно выбирать любые методы, подставлять на вкладке «Body» свои данные и проверять их работу.

В правой панели кнопкой «</>» можно сгенерировать готовые примеры кода вызова метода на PHP, Python и других языках, команд cURL, wget, и др.

Содержание

    (3)

    Комментарии

    oleksiy.lyubchenko
    Я не одразу розібрався, як працювати з API сховища. Сподіваюся, що це збереже комусь час.

    Робочий приклад авторизації і отримання вмісту кореневої папки сховища.

    const CDN_URL = 'https://a1b2c3d4e5f6g7h8.cdn.express';
    const
    CDN_USER = 'your-login';
    const CDN_PASS = 'your-password';

    function send_curl(string $method, array $fields, string $token = '') : array {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, CDN_URL . $method);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Storage-Token: ' . $token]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    curl_close($ch);
    return json_decode($result, true);
    }

    function get_token() : string {
    $curl = send_curl('/~/action/storage/auth/login/', ['username' => CDN_USER, 'password' => CDN_PASS]);
    return $curl['callback']['token'];
    }

    $token = get_token();
    $curl = send_curl('/~/action/storage/manage/ls/', ['path' => '/'], $token);
    $list = $curl['callback'];

    echo '<pre>';
    print_r($list);
    echo '</pre>';

    Наостанок, кілька важливих моментів:

    1. Тильду (~) в рядку команди - прибирати не можна (я подумав, що її треба замінити на адресу сховища).
    $url_1 = 'https://a1b2c3d4e5f6g7h8.cdn.express/~/action/storage/auth/login/';; // правильно
    $url_2 = 'https://a1b2c3d4e5f6g7h8.cdn.express/action/storage/auth/login/';; // неправильно

    2. Сховище очікує вхідні дані в JSON форматі.

    3. Доки ви ще не авториовані, $token - пустий рядок. Але при відправці пустого заголовка 'Storage-Token: ' - помилки немає.
    Відповідно ми маємо один варіант CURLOPT_HTTPHEADER, незважаючи чи є токен, чи немає.
    verliber
    Дякуємо за коментар, додали позначення типу даних для кожного методу та приклад коду для завантаження файлів.
    karlov
    Також додали приклад коду для заватаження файлу.
    brzhex
    Хотелось бы чтобы у хранилища был функционал обычной загрузки файлов по URL, как это сделано с torrent, а так же возможность указания времени жизни
    для таких файлов и\или автоматическое удаление таких файлов через N-количество обращений к ним (например автоматическое удаление файла после получения файла по API)
    karlov
    Загружать файлы в хранилище по ссылке можно с помощью файл-менеджера. Или речь об API, а не о ручной загрузке?

    По поводу удаления — в настройках хранилища есть опция автоматического удаления файлов старше указанного количества дней. Если подразумевается удаление только определённых файлов, то сейчас это можно организовать самостоятельно через API (собственным скриптом, который будет находить в хранилище файлы с нужными вам критериями и удалять с заданной периодичностью). Может у вас есть пример сервиса, где такая функция доступна из коробки.

    По поводу времени жизни сессии — в теории такое можно было бы реализовать для публичных ссылок, чтобы они срабатывали только заданное количество раз. Можете добавить такое предложение — https://www.ukraine.com.ua/#suggestion/ — и если оно наберёт достаточное количество голосов, то будет рассмотрено разработчиками.
    sir.malefici
    Ось вам скрипта на Python без залежностей https://gist.github.com/malefici/685fac67629c3c82cd189a200d57d00f
    papinaeda
    Очень не хватает функции проверки существования файла или каталога. Например, мне нужно узнать, есть ли картинка в кэше или нет, и мне приходится загружать весь список файлов директории, проходиться по нему циклом, чтобы узнать есть ли в этом массиве искомый файл или нет.
    karlov
    Внедрение такого метода не планируется. В качестве альтернативного варианта проверки наличия файла можно обращаться к нему по HTTP и проверять наличие ответа 200.
    brzhex
    Не хватает полного описания всех кодов ошибок (например при загрузке файла, если файл уже существует)
    karlov
    Описание ошибки возвращается в ответе сервера. Например, если загружаемый файл уже существует, в ответе будет «"error": "File exists"».
    brzhex
    Я имею ввиду HTTP-статусы, в документации не для всех методов указаны все возможные коды ответов (я про 404 и т.д). Вот например к той же ошибке «file exist какой код ответа? Только вручную проверять, хотелось бы здесь в документации видеть :)
    karlov
    При обращении к несуществующим файлам будет ответ 404, в остальных случаях будет ответ 400 с описанием ошибки в теле ответа. Возможно, добавим это в документацию, чтобы было проще ориентироваться.

    UPD: В статью добавлены описания кодов ответов.
    sanyva
    Очень не хватает метода для создания ZIP/TAR архива из указанной директории или выбранных файлов.

    В аналогичных сервисах (например, Amazon S3) есть возможность быстро собрать и скачать несколько файлов в одном архиве — это удобно для автоматизации и экономит время при работе с большим количеством данных.
    k.andrew
    Метод был добавлен, но вам забыли отписать. /~/api/archive
    sanyva
    Подскажите, а можно ли как то TAR получить?, zip слишком долго создает архив, не могли бы Вы расширить этот метод и до tar? это ускорит в разы получение большого кол-ва файлов из хранилища
    rudenko
    Речь идет о tar или tar.gz?
    brzhex
    Добавьте пожалуйста возможность указание флага для перезаписи файла, иначе приходится вручную слать запрос на проверку существования и удаления файла, что значительно добавляет задержки при выполнении кода
    karlov
    Передали ваше предложение на рассмотрение разработчикам.
    karlov
    Спасибо за предложение. В методе загрузки добавлена возможность включения режима перезаписи с помощью ?overwrite=1 (см. обновлённое описание метода).
    brzhex
    Большое спасибо! Очень оперативно)
    rodigy
    Не роздивлялись можливість зробити умовно вічні токени не прив'язані до користувачів, щоб не треба було проходити авторизацію а одразу йде запит з токеном.
    karlov
    Дякуємо за коментар. Інформація передана на розгляд розробникам.
    rudenko
    Стандарт OAuth 2.0 прописує цю процедуру, якщо зробити вічний токен, то це вже буде не безпечний OAuth 2.0, а авторизація з логіном і паролем при кожному запиті.
    vladj
    Чи створюється резервна копія даних в сховищі?
    karlov
    Раз на тиждень створюються резервні копії на серверах у Німеччині. Ці копії призначені виключно для технічних цілей і недоступні для користувачів.
    rodigy
    В запит на перевірку існування файлу, якщо передати замість адресу файла існуючу директорію то також повернеться 200, це так має бути чи баг. Для директорій є окремий єндпоінт.
    rodigy
    Бачу що так і має бути, але навіщо все в одному якщо є 2 різніх апі.
    k.andrew
    HEAD запит на api/file віддає в заголовках тип іноди та інше(див. заголовки x-stat-*). для директорії аналогу немає. про який саме метод ви пишите?