Пакет · sdk-s5w

Работа с папками и файлами

Папка в S5W — это не только способ сгруппировать файлы, но и набор правил для них: кому они видны, сколько хранятся и как кэшируются. Здесь — рецепты для папок, поиска файлов и изменения их места и имени.

Папки

Создать папку с правилами

php
use Flytachi\Winter\SDK\S5w\Enum\Retention;

$folders = $s5w->folders();

$folders->create('avatars', public: true);                    // видна всем, хранится всегда
$folders->create('tmp-exports', retention: Retention::WEEK);   // приватная, файлы живут неделю
Правило Что значит для файлов внутри
public: true доступны по publicUrl без ключа — для картинок на сайте, аватаров, публичных загрузок
public: false (по умолчанию) только с ключом, через privateUrl
retention удаляются сами через заданное время после создания файла — от дня до года

Имя папки — от 1 до 100 символов: буквы, цифры, пробел, ., _, -; начинается с буквы или цифры. Вложенных папок нет — уровень один. Занятое имя даст ConflictException.

Создать, только если её нет

Для кода, который запускается много раз (старт приложения, миграция), удобнее ensure():

php
$folder = $s5w->folders()->ensure('avatars', public: true);

ensure() сначала ищет папку и, если она есть, возвращает её как есть — переданные настройки к существующей папке не применяются. Если папки нет, создаёт её с этими настройками.

Найти папку

php
$folders->get('avatars');      // Folder или NotFoundException
$folders->find('avatars');     // Folder или null
$folders->exists('avatars');   // bool

Имя может содержать пробелы и кириллицу — SDK сам закодирует его в адресе.

Изменить папку

php
$folders->update('avatars', public: false);                  // меняется только видимость
$folders->update('tmp-exports', retention: Retention::DAY);  // только срок хранения
$folders->rename('avatars', 'userpics');                     // только имя

update() меняет только переданные параметры, остальные остаются прежними. Сервер принимает папку целиком, поэтому, когда передано не всё, SDK сначала читает текущую папку — это два запроса вместо одного.

Изменения доходят до файлов

Смена видимости переписывает флаг у всех файлов в папке. Смена срока хранения пересчитывает срок каждого файла от даты его создания: если перейти с YEAR на DAY, файлы старше суток удалятся при ближайшей очистке (она идёт раз в пять минут).

Кэш

Заголовок Cache-Control, с которым сервер раздаёт файлы папки, настраивается отдельно:

php
use Flytachi\Winter\SDK\S5w\Enum\CacheVisibility;

$folders->setCache('avatars', 86400, CacheVisibility::SHARED);   // public, max-age=86400
$folders->setCache('avatars', null, CacheVisibility::PRIVATE);   // private, max-age от бакета
$folders->resetCache('avatars');                                 // всё от бакета

null в параметре значит «взять у бакета». setCache() всегда передаёт оба значения. Подробнее о том, как сервер выбирает заголовок, — в документации S5W.

Список папок

php
$page = $folders->list(page: 1, limit: 25, search: 'user');

foreach ($folders->all() as $folder) {
  echo "{$folder->name} — {$folder->retention->name}\n";
}

Удалить папку

php
$folders->delete('tmp-exports');

Вместе с файлами

Папка удаляется вместе со всеми файлами внутри, без подтверждения и без возможности восстановить. Режима «переложить файлы в корень» нет.

Поиск файлов

Список с фильтрами

php
use Flytachi\Winter\SDK\S5w\Enum\FileSort;
use Flytachi\Winter\SDK\S5w\Enum\SortDirection;

$page = $s5w->files()->list(
  page: 1,
  limit: 25,
  search: 'invoice',             // часть имени, без учёта регистра
  folder: 'docs',                // одна папка
  sort: FileSort::SIZE,
  direction: SortDirection::DESC,
);

echo "Найдено {$page->total}, страница {$page->current} из {$page->pages}\n";
foreach ($page as $file) {
  echo "{$file->name}  {$file->content->size}\n";
}

Параметр folder: выбирает, где искать:

Значение Где ищет
не передан (null) во всём бакете
'docs' или объект Folder в одной папке
Folder::ROOT только среди файлов без папки (в корне)
php
use Flytachi\Winter\SDK\S5w\Entity\Folder;

$s5w->files()->list(folder: Folder::ROOT);   // только корень

Несуществующая папка в фильтре — ValidationException, а не пустой список.

Сортировка:

FileSort Порядок
CREATED (по умолчанию) по дате загрузки
NAME по имени
TYPE по MIME-типу, затем по имени
SIZE по размеру, затем по имени

Направление — SortDirection::DESC (по умолчанию, новые и большие сначала) или ASC.

Сортировка по имени учитывает регистр

Сервер сортирует имена побайтово: сначала идут заглавные буквы, потом строчные — Banana.txt, Report.md, apple.txt.

Перебрать все файлы

list() отдаёт одну страницу. Чтобы пройти по всем, есть all() — генератор, который сам запрашивает следующую страницу, когда закончилась текущая:

php
$total = 0;
foreach ($s5w->files()->all(folder: 'backups') as $file) {
  $total += $file->content->size;
}
echo "В backups {$total} байт\n";

Страницы берутся по 100 файлов (максимум сервера), поэтому для большинства папок это один запрос. Принимает те же фильтры, что list(), кроме номера страницы.

Не меняйте выборку во время обхода

Сервер листает по номерам страниц. Если удалять или переносить файлы прямо внутри foreach по all(), следующие страницы сдвинутся и часть файлов будет пропущена. Сначала соберите список — iterator_to_array($files->all(…), false), — потом меняйте.

Один файл

php
$file = $s5w->files()->get('FXOkqegbdrNRWQgc');   // File или NotFoundException
$file = $s5w->files()->find($id);                  // File или null
$s5w->files()->exists($id);                        // bool

Строку, которая не может быть id (не 16 символов из A-Za-z0-9_-), SDK отклоняет сам, без запроса: find() вернёт null. Это удобно, когда id приходит из адреса страницы. Проверить формат заранее можно через File::isValidId($id).

Изменение файлов

Переименовать

php
$file = $s5w->files()->rename($file, 'Q4 report.pdf');

Файл остаётся в своей папке, id не меняется — все ссылки продолжают работать. Имя сохраняется как передано: расширение сервер не проверяет и не добавляет. Если такое имя в папке уже есть — ConflictException.

Перенести

php
$file = $s5w->files()->move($file, 'archive');        // в папку по имени
$file = $s5w->files()->move($file, $archiveFolder);   // в папку-объект
$file = $s5w->files()->move($file, Folder::ROOT);     // в корень

Папка назначения обязательна: move($file) и move($file, null) — ошибка PHP ещё до запроса. Имя сохраняется. После переноса файл получает правила новой папки:

Куда Что меняется у файла
в публичную папку становится публичным, появляется publicUrl
в приватную становится приватным, publicUrl = null
в папку со сроком хранения срок считается от даты создания файла
в корень становится публичным

Корень делает файл публичным

Перенос приватного файла в корень открывает его всем по publicUrl, без ключа. Поэтому корень задаётся только явно — Folder::ROOT или ''.

Переименовать и перенести сразу

php
$file = $s5w->files()->update($file, 'Q4-final.pdf', 'archive');

update() задаёт имя и папку одним запросом и ничего не читает заранее. Оба значения обязательны.

Чем он отличается от rename() и move():

rename() / move() update()
запросов 2 (чтение + изменение) 1
что нужно передать только то, что меняется имя и папку
если кто-то изменил файл между чтением и записью изменение может откатиться к прочитанному нет: итог — ровно то, что вы передали

Берите update(), когда известны оба значения или нужно сделать оба изменения атомарно.

Удалить

php
$s5w->files()->delete($file);   // или delete($id)

Файл сразу исчезает из всех адресов раздачи, временные ссылки на него начинают отвечать 404. Повторное удаление — NotFoundException: удаление не идемпотентно, поэтому при повторе после обрыва связи 404 означает «уже удалено». Если такое же содержимое есть у другого файла (дедупликация), тот остаётся невредимым.

См. также