Продукт — FluxFiles

Возможности

Всё, что нужно современному файловому менеджеру

Создан для разработчиков, которым нужна гибкость.

Мульти-хранилище

Локальное, AWS S3, Cloudflare R2, SFTP через Flysystem v3 — меняйте в конфиге без правки кода.

Встраивайте куда угодно

iframe + postMessage SDK. Автономный UI на Alpine.js (без сборки). С любым фреймворком.

JWT авторизация + скоупинг

Префикс пути, права, белый список дисков, режим только владелец — или начните с готового набора прав viewer/editor/admin.

Пресеты ролей ACL

Выпускайте токены из пресетов viewer/editor/admin/superadmin — один параметр разворачивает нужные claims прав, дисков и области доступа вместо ручной сборки.

AI авто-теги

Claude / OpenAI vision — автоматический alt-текст, заголовок, теги.

Обрезка изображений

Инструмент обрезки с предустановками пропорций.

Оптимизация изображений

Автоматические WebP-варианты — миниатюра, средний, большой.

Предподписанные загрузки

Браузер загружает напрямую в S3/R2 — нулевая нагрузка на ваш сервер.

Загрузка частями

S3 multipart для файлов > 10МБ.

Полнотекстовый поиск

Индексированный поиск по именам, заголовкам, тегам — по умолчанию на файлах, либо ваша собственная SQL-база как опциональный бэкенд.

Метаданные в БД

Опциональный режим FLUXFILES_STORAGE_BACKEND=db — метаданные, индекс поиска/папок и журнал аудита хранятся в вашей собственной базе MySQL/PostgreSQL/SQLite вместо JSON-файлов. Байты файлов в обоих случаях остаются в хранилище.

Массовые операции

Множественный выбор: перемещение, копирование, удаление, скачивание.

Кросс-диск перенос

Копирование/перемещение между Локальным ↔ S3 ↔ R2.

Корзина

Восстановимое удаление с автоочисткой.

SEO метаданные

Заголовок, alt, подпись, теги — метаданные S3 (облако) или sidecar JSON (локально). Полнотекстовый поиск.

Тёмный режим

Светлая / тёмная / авто в UI и SDK.

16 языков

По умолчанию английский. Локаль через SDK, URL (?locale=) или FLUXFILES_LOCALE. RTL для арабского.

Журнал аудита

Все действия записи логируются.

Ограничение скорости

Token bucket для каждого пользователя.

Квота хранилища

Лимиты для каждого пользователя через JWT claims.

BYOB бакеты

Свой S3/R2 пользователя — учётные данные в JWT (AES-256-GCM).

Обнаружение дубликатов

Совпадение SHA-256 пропускает лишние загрузки кроме принудительной перезаписи.

Обновление токена SDK

onTokenRefresh при 401 — объединённое обновление, повтор, updateToken().

Bucket Doctor

Диагностика любого диска S3/R2 — учётные данные, чтение/запись/удаление, presign, CORS, multipart — с готовыми к вставке исправлениями IAM и CORS. Подключайте BYOB-бакеты за минуты.

Диск SFTP

Третий драйвер после S3/R2 — превратите любой VPS или хостинг в файловый менеджер.

Редактор кода / конфигов

Редактируйте текст и конфиги (wp-config.php, .env) в браузере, как в cPanel.

Zip и распаковка

Скачайте выбранное как zip или распакуйте архив — защита от zip-slip и бомб.

Водяной знак

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

WebP + AVIF по запросу

Отдавайте любой размер изображения как кэшированный AVIF/WebP по одному URL (согласование через Accept), с готовым адаптивным srcset.

Права SFTP

Меняйте права Unix (chmod) на SFTP-дисках через диалог в стиле cPanel.

SSH-терминал

Встройте собственный ttyd / gotty / wetty как терминал внутри приложения на SFTP-дисках через бесплатный клейм terminal_pty_url — собственной оболочки в FluxFiles нет.

Git-деплой в один клик

Pull и reset Git-репозитория на вашем SFTP-сервере прямо из файлового менеджера — фиксированная форма, не произвольная оболочка, хуки по умолчанию отключены.

Панель использования

Хранилище с первого взгляда — квота и разбивка по типам и папкам.

Предпросмотр медиа

Встроенный просмотр фото, видео, аудио и PDF; приватные локальные медиа — безопасно.

Быстрая установка

Запуск за 2 минуты

composer require fluxfiles/fluxfiles
cp vendor/fluxfiles/fluxfiles/.env.example vendor/fluxfiles/fluxfiles/.env
# vendor/fluxfiles/fluxfiles/.env  (read only from inside the package)
# Real environment variables win over this file and are preferred in production
# (Composer may remove a vendor .env on update).
FLUXFILES_SECRET=<output of: openssl rand -hex 32>
FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com
<?php
require_once 'vendor/autoload.php';
// embed.php is not autoloaded — require it for fluxfiles_token()
require_once 'vendor/fluxfiles/fluxfiles/embed.php';

$token = fluxfiles_token([
    'user'   => 'user-123',
    'perms'  => ['read', 'write', 'delete'],
    'disks'  => ['local'],     // s3 / r2 need their own credentials in .env
    'prefix' => 'user-123/',
    'ttl'    => 3600,
]);
php vendor/bin/fluxfiles serve --port=8080
# then open http://127.0.0.1:8080/public/
composer require fluxfiles/laravel
php artisan vendor:publish --tag=fluxfiles-config
php artisan storage:link
# .env — proxy mode is the default: the API runs through your Laravel routes,
# no separate FluxFiles server is needed.
FLUXFILES_SECRET=<output of: openssl rand -hex 32>

# Only for FLUXFILES_MODE=standalone (FluxFiles on its own server):
# FLUXFILES_MODE=standalone
# FLUXFILES_ENDPOINT=https://fm.yourdomain.com
<?php
// app/FluxFiles/TenantClaims.php — REQUIRED: without a claims resolver
// <x-fluxfiles> renders "not available".
namespace App\FluxFiles;

use FluxFiles\Laravel\ClaimsResolver;
use Illuminate\Contracts\Auth\Authenticatable;

class TenantClaims implements ClaimsResolver
{
    public function resolve(Authenticatable $user): array
    {
        return [
            'prefix' => 'users/' . $user->getAuthIdentifier(),
        ];
    }
}
// config/fluxfiles.php
'claims_resolver' => \App\FluxFiles\TenantClaims::class,
// Laravel 11 / 12 — bootstrap/app.php: exclude the proxy routes from CSRF (else 419)
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: ['api/fm/*']);
})

// Laravel 10 — app/Http/Middleware/VerifyCsrfToken.php
// protected $except = ['api/fm/*'];
<x-fluxfiles disk="local" mode="picker" height="600px" />
# Not yet on WordPress.org — install the release zip:
# 1. Download fluxfiles-<version>.zip from https://github.com/thai-pc/fluxfiles/releases
# 2. Plugins -> Add New -> Upload Plugin -> Activate
# 3. Settings -> FluxFiles: set the JWT secret (>= 32 bytes) and storage
# 4. Add the shortcode (or the FluxFiles block) to any page or post:
[fluxfiles]
npm install @fluxfiles/node   # Node >= 16
// Express / Next.js route — mint a token from your JS backend (no PHP)
import { createToken } from '@fluxfiles/node';

app.get('/fluxfiles-token', (req, res) => {
    const token = createToken({
        secret: process.env.FLUXFILES_SECRET, // >= 32 bytes
        userId: req.user.id,
        perms: ['read', 'write', 'delete'],
        prefix: `users/${req.user.id}`,
        ttl: 3600,
    });
    res.json({ token });
});
pip install fluxfiles-token
# FastAPI / Django / Flask route — mint a token from your Python backend (no PHP)
import os

from fastapi import Depends
from fluxfiles_token import create_token

@app.get("/fluxfiles-token")
def fluxfiles_token(user=Depends(current_user)):
    token = create_token(
        secret=os.environ["FLUXFILES_SECRET"],  # >= 32 bytes
        user_id=user.id,
        perms=["read", "write", "delete"],
        prefix=f"users/{user.id}",
        ttl=3600,
    )
    return {"token": token}
{
  "mcpServers": {
    "fluxfiles": {
      "command": "npx",
      "args": ["-y", "@fluxfiles/mcp"],
      "env": {
        "FLUXFILES_URL": "<your FluxFiles URL>",
        "FLUXFILES_TOKEN": "<scoped JWT>"
      }
    }
  }
}
# Claude Code (Node >= 18)
claude mcp add fluxfiles -e FLUXFILES_URL=<your FluxFiles URL> -e FLUXFILES_TOKEN=<scoped JWT> -- npx -y @fluxfiles/mcp
# Read-only by default. Opt in to writes:
FLUXFILES_MCP_WRITE=1
# and to move_to_trash:
FLUXFILES_MCP_DELETE=1

Агент может работать только с тем, что разрешает его JWT, — его дисками, префиксом пути и правами. Выдайте ему узкий токен только для чтения.

npm install fluxfiles
<!-- or load a pinned CDN build (never @latest) -->
<script src="https://unpkg.com/fluxfiles@1.0.1/fluxfiles.js"></script>
<div id="file-picker" style="height:600px"></div>

<script>
FluxFiles.open({
    endpoint: 'https://your-fluxfiles-host',
    token: 'eyJhbGci...',   // JWT minted by your backend
    disk: 'local',
    mode: 'picker',
    container: '#file-picker',
    onSelect: function(file) {
        console.log('Selected:', file.url);
    },
    async onTokenRefresh() {
        const r = await fetch('/api/auth/refresh-fluxfiles-token');
        const { token } = await r.json();
        return token;
    }
});
</script>
npm install @fluxfiles/react
import { FluxFilesModal } from '@fluxfiles/react';

<FluxFilesModal
    open={open}
    endpoint="https://your-api.com"
    token={token}
    onSelect={(file) => console.log(file)}
    onClose={() => setOpen(false)}
/>
npm install @fluxfiles/vue
<script setup>
import { FluxFilesModal } from '@fluxfiles/vue';
</script>

<FluxFilesModal
    v-model:open="open"
    endpoint="https://your-api.com"
    :token="token"
    @select="onSelect"
    @close="open = false"
/>
docker run -p 8080:80 \
  -e FLUXFILES_SECRET="$(openssl rand -hex 32)" \
  -e FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com \
  -v fluxfiles-data:/app/packages/core/storage \
  ghcr.io/thai-pc/fluxfiles:1.1
# UI: http://localhost:8080/public/
git clone https://github.com/thai-pc/fluxfiles.git
cd fluxfiles/packages/core
composer install
cp .env.example .env
# packages/core/.env — the placeholder secret is rejected, set a real one
FLUXFILES_SECRET=<output of: openssl rand -hex 32>
FLUXFILES_ALLOWED_ORIGINS=http://localhost:8080
# print dev tokens (run from the repo root)
php packages/core/tests/generate-token.php
php -S localhost:8080 router.php

# UI: http://localhost:8080/public/index.html?token=<token>
# ?token= is dev-only — it is stripped from the URL on boot.
# Real apps pass the JWT via the SDK / postMessage, never in a URL.

Перед запуском в продакшен: задайте FLUXFILES_SECRET длиной не менее 32 байт и FLUXFILES_ALLOWED_ORIGINS (или FLUXFILES_FRAME_ANCESTORS). Сделайте корень пакета document root и закройте в nginx /_fluxfiles/ и .env. Никогда не передавайте основной JWT в URL — адаптеры отправляют его через postMessage. DEPLOYMENT.md

Работает с

Laravel WordPress React / Next.js Vue / Nuxt CKEditor 4 CKEditor 5 TinyMCE Summernote Any framework

Интеграции

Готовые адаптеры для вашего стека

Официальные адаптеры нативно встраивают FluxFiles во фреймворки и редакторы, которыми вы уже пользуетесь.

Используйте CKEditor или TinyMCE со своим хранилищем — подписка на CKBox или Tiny Drive не нужна. FluxFiles добавляет кнопку на панель инструментов для просмотра и вставки файлов; это не замена этих продуктов по функциям один к одному.

Laravel
PHP
WordPress
Plugin
React
Component
Vue / Nuxt
Component
CKEditor 4
Plugin
CKEditor 5
Plugin
TinyMCE
Plugin
Summernote
Plugin

Встраивание

Встройте в несколько строк

Подключите fluxfiles.js, передайте JWT, выпущенный на сервере, и разместите полноценный файловый менеджер — или модальное окно выбора файлов — на любой странице.

<!-- npm install fluxfiles, or a pinned CDN build -->
<script src="https://unpkg.com/fluxfiles@1.0.1/fluxfiles.js"></script>

FluxFiles.open({
  endpoint: 'https://fm.example.com',
  token: 'eyJhbGci...',   // JWT from your backend
  disk: 'local',
  mode: 'picker',         // select & close
  theme: 'auto',
  onSelect(file) {
    // { url, key, name, size, disk, meta, variants }
    document.querySelector("#img").src = file.url;
  },
});
<div id="fm" style="height:600px"></div>

FluxFiles.open({
  endpoint: 'https://fm.example.com',
  token: 'eyJhbGci...',
  mode: 'browser',          // full manager, stays open
  container: '#fm',         // omit for a modal overlay
  disks: ['local', 's3', 'r2'],
});

FluxFiles.on('FM_EVENT', (e) => console.log(e.event));
FluxFiles.navigate('/photos/2024');
import { FluxFilesModal } from '@fluxfiles/react';

function Picker({ open, setOpen, token }) {
  return (
    <FluxFilesModal
      open={open}
      endpoint="https://fm.example.com"
      token={token}
      onSelect={(file) => console.log(file.url)}
      onClose={() => setOpen(false)}
    />
  );
}

Токены выпускаются на сервере — никогда не передавайте секрет в браузер.

Почему FluxFiles

Создан для того, о чём другие забыли

Свайп для сравнения
Функция FluxFiles elFinder Laravel-FM RichFilemanager Responsive FM
S3 + R2 + Локальное + SFTP ✓ ⚠ ⚠ ⚠ ✗
Встраивание в любой фреймворк ✓ ⚠ ✗ ⚠ ✗
JWT авторизация + скоупинг ✓ ✗ ✗ ✗ ✗
SEO метаданные ✓ ✗ ✗ ✗ ✗
AI авто-теги ✓ ✗ ✗ ✗ ✗
Обрезка изображений ✓ ✓ ✗ ✗ ✗
Загрузка частями ✓ ✗ ✗ ✗ ✗
Полнотекстовый поиск ✓ ✗ ✗ ✗ ✗
Тёмный режим ✓ ✗ ⚠ ✗ ✗
16 языков ✓ ✓ ✗ ✗ ✗
PHP ≥ 8.1 ✓ ✓ ✗ ✓ ✓
Активно поддерживается ✓ ✓ ⚠ ✗ ✗
Современный UI ✓ ✗ ⚠ ✗ ✗
Возможность FluxFiles Filestack Uploadcare Cloudinary Supabase Storage
Self-hosted (работает в вашей инфраструктуре) ✓ ✗ ✗ ✗ ⚠
BYOB — собственный бакет каждого клиента ✓ ⚠ ⚠ ✗ ✗
Встраиваемый UI файлового менеджера ✓ ✓ ✓ ⚠ ✗
Открытый код (MIT) ✓ ✗ ✗ ✗ ✓
Без SaaS-платы за хранение / за загрузку ✓ ✗ ✗ ✗ ⚠
Мультихранилище (S3 / R2 / локально) ✓ ⚠ ✗ ✗ ✗
Встроенное ограничение токена по арендатору ✓ ⚠ ⚠ ⚠ ⚠

Сравнение отражает типичные предложения по умолчанию; каждый продукт силён в своей области. Ниша FluxFiles — сочетание встраиваемости, self-hosted и bring-your-own-bucket.

Сравнение актуально на November 2026, подготовлено независимо — сообщите об ошибке через репозиторий на GitHub.

Вопросы и ответы

Часто задаваемые вопросы

Как работает аутентификация?
Stateless JWT (HS256): вы выпускаете токен на сервере с детальными клеймами (права, диски, область пути, лимиты), поэтому каждый пользователь видит только то, что вы разрешили.
Нужен ли моим пользователям аккаунт FluxFiles?
Нет. FluxFiles доверяет JWT, выпущенному вашим приложением, поэтому подключается к вашей существующей аутентификации — отдельной системы пользователей не нужно.
Что нужно для запуска?
PHP 8.1+ (протестировано 8.1–8.5) с расширениями gd, curl, json, openssl, mbstring, fileinfo (для Extract — ещё zip) и Composer 2 — либо Docker-образ ghcr.io/thai-pc/fluxfiles. Укажите диск, задайте секрет и разрешённые origin — и запускайте; хватит небольшого VPS.
Могут ли разные пользователи иметь разные права?
Да. Выпустите токен с детальными клеймами (чтение/запись/удаление, диск, префикс пути, лимиты загрузки, разрешённые расширения, owner-only), либо используйте одну из четырёх встроенных ролевых пресетов — viewer, editor, admin, superadmin — чтобы ограничить токен одной строкой вместо перечисления каждого клейма вручную.
Нужно ли мне разворачивать базу данных?
Нет. По умолчанию все метаданные (информация о файлах, поисковый индекс, журнал аудита) хранятся рядом с вашими файлами как JSON-файлы-спутники — ничего дополнительного разворачивать или бэкапить не нужно. Если вы предпочитаете вести этот учёт в собственной MySQL, PostgreSQL или SQLite, опциональный режим FLUXFILES_STORAGE_BACKEND=db переносит его туда; байты файлов при этом всегда остаются в вашем хранилище.
Есть ли ограничения на использование?
Само ядро не накладывает искусственных ограничений — нет предела по числу активных пользователей в месяц, нет принудительных призывов к апгрейду. Вы сами задаёте лимиты через JWT-клеймы: квоты хранилища на пользователя, ограничения размера/расширения загрузки и встроенный ограничитель скорости (по умолчанию 60 чтений / 10 записей в минуту, настраивается).