7.17. Work with storage content via API

Notes:

  • The instruction describes the API for working with content of the storage. To work with the storage itself, use general API.
  • Limits on the number of requests: in the old version of the API were identical to the limits of the general API, in the new version of the API there are no such limits (you can send more requests).
  • All methods support only full paths, without ...

To send requests, use your storage address.

Getting a token:

  1. Create a web interface user (if not created).
  2. Authorize with the login and password of the created user and get the token.

Then use the obtained token when working with the rest of the methods (the token is specified in the Authorization: Bearer header).

Authorization and uploading a file to the storage:

<?php

// Storage host address, displayed at the top of the section in the control panel
$host = 'example.cdn.express';

// File to be uploaded to the storage
$file = '/path/to/local/file.ext';

// Path for uploading to storage and original file name
$path = '/upload/dir/' . basename($file);

// Web access user login to the storage (data can be obtained in the control panel on the "Users and API" tab)
$login = 'storage_login';

// Web user password for accessing the storage
$password = 'storage_password';

$curl = curl_init();

// Authorization
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 {
    // Check that the host, login and password are correct
    echo 'Authentication failed. Check host, login and password.' . PHP_EOL;
    exit;
}

// File upload (if the file already exists in the storage, there will be an error)
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);

Methods for working with tokens.

Important points:

  • To use all methods at the moment of authorization the user must have write permission set. Without this permission, only getting file list and downloading will be available.
  • Whenever you change user rights, you need to log in again and get a new token.

PUT /~/api/auth

Parameters in the request body:
multipart/form-data

  • login — web access user login.
  • password — web access user password.
  • remember — token validity period:
    • 0 — 6 hours (default value).
    • 1 — 7 days.

Authorizes under the specified user and returns a token with an expiration date.

Response:

  • token — token to use in the Authorization: Bearer header when using the rest of the methods.
  • till — token expiration timestamp.

DELETE /~/api/auth

The token is transferred in the header (as in the other methods).

Deactivates the previously obtained token.

Methods for working with directories and retrieving their contents.

GET /~/api/directory

Request parameters:

  • path — path to the directory whose contents are to be retrieved (it is possible to specify several path parameters in one request — the data will be returned by unique values, sorted by path length in ascending order).
  • recursive (optional) — recursive data retrieval:
    • 0 — get the contents of only the specified directory (default value).
    • 1 — get the contents of the specified directory and all its subdirectories.
  • iterator (optional) — getting data in a special format, when instead of one large JSON the response contains strings with separate JSON for each directory element. This allows you to significantly save RAM when processing the contents of directories with a large number of items — you can view the response line by line, find JSON of only the required item and unpack it without having to unpack a large JSON with all items.
    • 0 — get the response as a single large JSON (default value).
    • 1 — get the response as lines with separate JSON.

The response contains a list of objects with information on each of them:

  • name — file or directory name.
  • path — path to the object from the storage root.
  • isDirectory — object type: directory or not.
  • size — file size in bytes (for directories it is always 4096).
  • mtime — timestamp of the last time the content of the object was changed.
  • ctime — timestamp of the last change to the object's metadata.
  • birthtime — timestamp of object creation or uploading.
  • media — media type (for media files).
  • ext — extension (for files with an extension).
  • share — information about the presence of public link: public link ID or null (with multiple path parameters or when retrieving data recursively it is always null).
  • uri — URI of the file depending on the public access status:
    • Public access enabled — direct link.
    • Public access disabled — secure link (starts with /~/secure/).

PUT /~/api/directory

Parameters in the request body:
multipart/form-data

  • path — path to the new directory.

Creates a new directory at the specified path.

POST /~/api/directory

Parameters in the request body:
multipart/form-data

  • path — path to the directory to be renamed or moved.
  • dest — new path or directory name (path must exist).
  • overwrite — overwrite mode if the target directory already exists:
    • 0 — do not overwrite and return an error (default value).
    • 1 — replace the contents of an existing directory.

Renames or moves the specified directory.

DELETE /~/api/directory

Request parameters:

  • path — path to the directory to be deleted.

Deletes the specified directory with all its contents. Parent directories are not affected.

Methods for working with files.

Notes:

  • Maximum size of the uploaded file — 50 GB. If you try to upload a larger file, the server will return "413 Request Entity Too Large".
  • Statistics are available on the number and amount of uploaded data.

PUT /~/api/file

Request parameters:

  • path — path to upload with the file name.
  • overwrite — overwrite mode if the target file already exists:
    • 0 — do not overwrite and return an error (default value).
    • 1 — replace an existing file.

Uploads the file to the specified path (from the root of the storage).

For an example of PHP code, see. at the beginning of the article.

Command to upload a file from console:

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'

To maximize speed, files are not downloaded using a method, but rather a GET request via a direct or secure link to the file.

  1. Get the file list of the directory where the file you want to download is located.
  2. From the list, get the URI of the desired file.
  3. Send a GET request to the storage address with the received URI.

PUT /~/api/archive

Parameters in the request body:
application/json

  • items — paths to files and directories that need to be downloaded.

Downloads the listed objects as a .zip archive (all objects must exist).

HEAD /~/api/file

Request parameters:

  • path — path to the file or directory whose existence is to be checked.

Checks if a file or directory exists at the specified path: response 200 — exists, response 404 — does not exist.

POST /~/api/file

Parameters in the request body:
multipart/form-data

  • path — path to the file to be renamed or moved.
  • dest — new path or file name (path must exist).
  • overwrite — overwrite mode if the target file already exists:
    • 0 — do not overwrite and return an error (default value).
    • 1 — replace an existing file.

Renames or moves the specified file.

DELETE /~/api/file

Request parameters:

  • path — path to the file to be deleted.

Deletes the specified file. Parent directories are not affected.

Methods for working with public links.

PUT /~/api/share

Request parameters:

  • path — path to the file or directory for which you want to create a public link.
  • write — access status for changing the directory contents: 1 (access allowed) or 0 (access denied).
  • deathtime (optional) — timestamp for automatic link deletion (must be later than the current date, 0 — do not delete).

Creates a public link for the specified object.

Response:

  • id — public link ID.
  • path — path to the public link object.
  • birthtime — timestamp of the public link creation.
  • isDirectory — object type: directory or not.
  • exists — existence of a public link object (always true when created).
  • deathtime — timestamp for automatic link deletion (if passed in the request) or 0.
  • writeAccess — status of access to changing directory contents (always false by default, configurable by a separate method),
  • uri — URI of the public link (starts with /~/share/).

GET /~/api/share

Request parameters:

  • id (optional) — ID of the public link you want to retrieve data from.

Returns the list of public links and their data. If public link ID is specified — returns data of this link only.

The response contains a link list with information about each link (or information about a specific link if the request was for an ID):

  • id — public link ID.
  • path — path to the public link object.
  • isDirectory — object type: directory or not.
  • writeAccess — status of access to changing directory contents (always false by default, configurable by a separate method),
  • birthtime — timestamp of the public link creation.
  • deathtime — timestamp for automatic link deletion (if passed in the request) or 0.
  • exists — existence of the public link object (if the file or directory has been renamed, moved or deleted, it will be false).
  • uri — URI of the public link (starts with /~/share/).

POST /~/api/share

Request parameters:

  • id — ID of the public link for which you want to change permissions (only for directory links).

Parameters in the request body:
multipart/form-data

  • write — access status for changing the directory contents: 1 (access allowed) or 0 (access denied).

Sets the public link's permissions to modify the contents of the directory.

The response is similar to getting a link list.

DELETE /~/api/share

Request parameters:

  • id — ID of the public link to be deleted.

Deletes the public link with the specified ID. The object pointed to by the link is not affected.

Attention!

Refreshing the secret key is performed via control panel or general API

GET /~/api/link

Request parameters:

  • path — path to the file from the storage root.
  • time (optional) — timestamp of the link's expiration (must be later than the current date).
  • ip (optional) — IP address that will be allowed to access the file via the link.

Generates and returns a Secure Link for the specified file with the given parameters.

Response:

  • token — encoded hash of the set of data consisting of the secret key, path, and parameters.
  • uri — URI of the link (starts with /secure/).
  • url — full link.
  • params:
    • ip — IP address for which access to the file via the link is allowed (if passed in the request).
    • time — timestamp of the link's expiration (if passed in the request).
    • path — path to the file from the storage root.
  • stat:
    • size — size of the file to which the link points (in bytes).
    • atimeMs — timestamp of the last access to the file (in milliseconds).
    • mtimeMs — timestamp of the last modification of the file content (in milliseconds).
    • ctimeMs — timestamp of the last modification of the file metadata (in milliseconds).
    • birthtimeMs — timestamp of file creation (in milliseconds).
  • 200 — request successfully completed.
  • 400 — error while performing request.
    • The response body will contain a description of the error, for example, "File exists" if the file being uploaded already exists, or "Item not found" if the public link ID cannot be found.
  • 401 — authorization not completed.
    • The response body will contain either "Invalid credential 'login' or 'password'" if the error occurred during authorization, or "Unauthorized" in all other cases.
  • 403 — access denied.
  • 404 — the file or path specified in the request does not exist..
  • 429 — too many requests.
  • 502/503 — you need to wait before sending the next request.
    • For example, the request was received at the moment the API was restarted, or the server was overloaded and did not have time to process the request.

Depending on the authorization status and request type, API responses contain additional headers.

For all requests:

  • x-storage-name — storage name or alias (if set).
  • x-storage-logo — logo from storage settings: if set — URL of the logo file (cdn.adm.tools domain).
  • x-storage-mode — status of the view when opened in storage settings: list (list) or table (gallery).

For requests with authorization:

  • x-user-login — web access user login.
  • x-user-write — user's web access write permission: 1 (has access) or 0 (no access).
  • x-user-tilltoken expiration timestamp.

For existence check and download requests:

  • x-stat-directory — object type: directory or not.
  • x-stat-mtime — timestamp of the last time the content of the object was changed.
  • x-stat-ctime — timestamp of the last change to the object's metadata.
  • x-stat-birthtime — timestamp of object creation or uploading.
  • x-stat-size — file size in bytes (for directories it is always 4096).
Postman — application for testing API.

Preparing to work with Postman:

  1. Importing collection and environment files:
    1. Download files:
    2. In the main menu, select "File → Import" (or press Ctrl+O), select the downloaded files and import them.
  2. Set up the environment:
    1. In the left pane, select "Environments".
    2. From the list of environments, select "storage".
    3. In the "Current value" column, enter your data and click "Save":
      • domain — address of your storage.
      • username — storage user name.
      • password — storage user password.
    4. In the upper right corner, select "storage".

Authorization:

  1. In the left pane, select "Collections".
  2. In the collection list, expand "storage" and select the "authorization" method.
  3. Click "Send" — method will return the token and Postman will automatically substitute the token into the environment.

Then you can select any methods, substitute your data on the "Body" tab and check their work.

In the right panel with the button "</>" you can generate ready-made code samples of method calls in PHP, Python and other languages, cURL, wget, etc. commands.

Content

    (3)

    Comments

    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
    Раз на тиждень створюються резервні копії на серверах у Німеччині. Ці копії призначені виключно для технічних цілей і недоступні для користувачів.