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) есть возможность быстро собрать и скачать несколько файлов в одном архиве — это удобно для автоматизации и экономит время при работе с большим количеством данных.
    brzhex
    Добавьте пожалуйста возможность указание флага для перезаписи файла, иначе приходится вручную слать запрос на проверку существования и удаления файла, что значительно добавляет задержки при выполнении кода
    karlov
    Передали ваше предложение на рассмотрение разработчикам.
    karlov
    Спасибо за предложение. В методе загрузки добавлена возможность включения режима перезаписи с помощью ?overwrite=1 (см. обновлённое описание метода).
    brzhex
    Большое спасибо! Очень оперативно)
    rodigy
    Не роздивлялись можливість зробити умовно вічні токени не прив'язані до користувачів, щоб не треба було проходити авторизацію а одразу йде запит з токеном.
    karlov
    Дякуємо за коментар. Інформація передана на розгляд розробникам.
    rudenko
    Стандарт OAuth 2.0 прописує цю процедуру, якщо зробити вічний токен, то це вже буде не безпечний OAuth 2.0, а авторизація з логіном і паролем при кожному запиті.
    vladj
    Чи створюється резервна копія даних в сховищі?
    karlov
    Раз на тиждень створюються резервні копії на серверах у Німеччині. Ці копії призначені виключно для технічних цілей і недоступні для користувачів.