Produit — FluxFiles
Tout ce dont un gestionnaire de fichiers moderne a besoin
Conçu pour les développeurs qui ont besoin de flexibilité.
Multi-stockage
Local, AWS S3, Cloudflare R2, SFTP via Flysystem v3 — changez par la config, sans modifier le code.
Intégration partout
iframe + SDK postMessage. L'UI autonome utilise Alpine.js (zéro build). Compatible avec tout framework.
Auth JWT + portée
Préfixe de chemin par utilisateur, permissions, liste blanche de disques, mode owner-only — ou partez d'un préréglage de rôle viewer/editor/admin.
Préréglages de rôle ACL
Émettez des tokens à partir de préréglages viewer/editor/admin/superadmin — un seul paramètre déploie les bons claims de permission, disque et portée au lieu de les assembler à la main.
AI auto-tag
Claude / OpenAI vision — alt texte, titre, tags automatiques.
Recadrage d'image
Outil de recadrage avec ratios prédéfinis.
Optimisation d'image
Variantes WebP automatiques — miniature, moyen, grand.
Uploads présignés
Le navigateur uploade directement vers S3/R2 — zéro bande passante serveur.
Upload par morceaux
S3 multipart pour fichiers > 10Mo.
Recherche plein texte
Recherche indexée par noms, titres, tags — basée fichier par défaut, ou votre propre base de données SQL en option.
Métadonnées adossées à une BD
Mode optionnel FLUXFILES_STORAGE_BACKEND=db — métadonnées, index de recherche/dossiers et journal d'audit vivent dans votre propre base MySQL/PostgreSQL/SQLite au lieu de fichiers JSON. Les octets des fichiers restent stockés côté stockage dans les deux cas.
Opérations en masse
Sélection multiple : déplacer, copier, supprimer, télécharger.
Transfert cross-disk
Copier/déplacer entre Local ↔ S3 ↔ R2.
Corbeille
Suppression réversible avec purge automatique.
Métadonnées SEO
Titre, alt, légende, tags — métadonnées objet S3 (cloud) ou JSON sidecar (local). Recherche plein texte.
Mode sombre
Clair / sombre / auto dans l'UI et le SDK.
16 langues
Anglais par défaut. Définissez la locale via SDK, URL (?locale=) ou FLUXFILES_LOCALE. RTL pour l'arabe.
Journal d'audit
Toutes les actions d'écriture enregistrées.
Limitation de débit
Token bucket par utilisateur pour la protection API.
Quota de stockage
Limites par utilisateur via JWT claims.
Buckets BYOB
Les utilisateurs apportent leur S3/R2 — identifiants chiffrés dans le JWT (AES-256-GCM).
Détection des doublons
Correspondance SHA-256 — ignore les uploads redondants sauf écrasement forcé.
Rafraîchissement du token SDK
onTokenRefresh sur 401 — refresh fusionné, retry, et updateToken() pour rotation proactive.
Bucket Doctor
Diagnostique n’importe quel disque S3/R2 — identifiants, lecture/écriture/suppression, presign, CORS, multipart — avec des correctifs IAM et CORS prêts à coller. Intégrez un bucket BYOB en quelques minutes.
Disque SFTP
Un 3ᵉ pilote après S3/R2 — transformez tout VPS ou hébergement en gestionnaire.
Éditeur code / config
Éditez fichiers texte et config (wp-config.php, .env) dans le navigateur, façon cPanel.
Zip & Extraction
Téléchargez une sélection en zip ou extrayez sur place — anti zip-slip & bombe.
Filigrane
Appliquez un filigrane texte ou logo à la volée — le fichier source reste intact.
WebP + AVIF à la demande
Servez toute taille d'image en AVIF/WebP mis en cache via une seule URL (négociée par Accept), avec srcset responsive prêt.
Permissions SFTP
Modifiez les permissions Unix (chmod) sur disques SFTP via une boîte façon cPanel.
Terminal SSH
Intégrez votre propre ttyd / gotty / wetty comme terminal dans l'application sur les disques SFTP via le claim gratuit terminal_pty_url — FluxFiles ne fournit aucun shell.
Déploiement Git en un clic
Pull et reset d'un dépôt Git sur votre serveur SFTP directement depuis le gestionnaire de fichiers — forme fixe, pas de shell arbitraire, hooks désactivés par défaut.
Tableau de bord d'usage
Visualisez le stockage d'un coup d'œil — quota et répartition par type et dossier.
Aperçu média
Aperçu image, vidéo, audio & PDF en ligne ; médias locaux privés diffusés en sécurité.
Opérationnel en 2 minutes
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 L'agent ne peut toucher que ce que son JWT autorise — ses disques, son préfixe de chemin et ses permissions. Donnez-lui un jeton restreint, en lecture seule.
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. Mise en production : définissez un FLUXFILES_SECRET d'au moins 32 octets et FLUXFILES_ALLOWED_ORIGINS (ou FLUXFILES_FRAME_ANCESTORS). Faites de la racine du package votre document root et interdisez /_fluxfiles/ et .env dans nginx. Ne mettez jamais le JWT principal dans une URL — les adaptateurs le transmettent via postMessage. DEPLOYMENT.md
Compatible avec
Intégrations
Des adaptateurs prêts à l'emploi pour votre stack
Les adaptateurs officiels intègrent nativement FluxFiles aux frameworks et éditeurs que vous utilisez déjà.
Utilisez CKEditor ou TinyMCE avec votre propre stockage, sans abonnement à CKBox ni à Tiny Drive. FluxFiles ajoute un bouton de barre d'outils pour parcourir et insérer des fichiers ; il ne remplace pas ces produits fonctionnalité par fonctionnalité.
Intégration
Intégrez-le en quelques lignes
Chargez fluxfiles.js, passez un JWT généré côté serveur, et insérez un gestionnaire de fichiers complet — ou une fenêtre de sélection — dans n'importe quelle page.
<!-- 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)}
/>
);
} Les jetons sont générés côté serveur — n'envoyez jamais votre secret au navigateur.
Conçu pour ce que les autres ont oublié
| Fonctionnalité | FluxFiles | elFinder | Laravel-FM | RichFilemanager | Responsive FM |
|---|---|---|---|---|---|
| S3 + R2 + Local + SFTP | ✓ | ⚠ | ⚠ | ⚠ | ✗ |
| Intégration tout framework | ✓ | ⚠ | ✗ | ⚠ | ✗ |
| Auth JWT + portée | ✓ | ✗ | ✗ | ✗ | ✗ |
| Métadonnées SEO | ✓ | ✗ | ✗ | ✗ | ✗ |
| AI auto-tag | ✓ | ✗ | ✗ | ✗ | ✗ |
| Recadrage d'image | ✓ | ✓ | ✗ | ✗ | ✗ |
| Upload par morceaux | ✓ | ✗ | ✗ | ✗ | ✗ |
| Recherche plein texte | ✓ | ✗ | ✗ | ✗ | ✗ |
| Mode sombre | ✓ | ✗ | ⚠ | ✗ | ✗ |
| 16 langues | ✓ | ✓ | ✗ | ✗ | ✗ |
| PHP ≥ 8.1 | ✓ | ✓ | ✗ | ✓ | ✓ |
| Maintenance active | ✓ | ✓ | ⚠ | ✗ | ✗ |
| UI moderne | ✓ | ✗ | ⚠ | ✗ | ✗ |
| Capacité | FluxFiles | Filestack | Uploadcare | Cloudinary | Supabase Storage |
|---|---|---|---|---|---|
| Auto-hébergé (tourne dans votre infra) | ✓ | ✗ | ✗ | ✗ | ⚠ |
| BYOB — le bucket de chaque client | ✓ | ⚠ | ⚠ | ✗ | ✗ |
| UI de gestion de fichiers intégrable | ✓ | ✓ | ✓ | ⚠ | ✗ |
| Open source (MIT) | ✓ | ✗ | ✗ | ✗ | ✓ |
| Aucun frais SaaS au stockage / à l’upload | ✓ | ✗ | ✗ | ✗ | ⚠ |
| Multi-stockage (S3 / R2 / local) | ✓ | ⚠ | ✗ | ✗ | ✗ |
| Portée de jeton par locataire intégrée | ✓ | ⚠ | ⚠ | ⚠ | ⚠ |
Le comparatif reflète les offres par défaut habituelles ; chaque produit excelle dans son domaine. La niche de FluxFiles est la combinaison intégrable, auto-hébergée et bring-your-own-bucket.
Comparaison à jour au November 2026, réalisée de manière indépendante — consultez le dépôt GitHub pour signaler une correction.
FAQ