产品 — FluxFiles

功能

现代文件管理器所需的一切

为需要灵活性的开发者而构建。

多存储

本地、AWS S3、Cloudflare R2, SFTP 通过 Flysystem v3 — 仅改配置即可切换。

嵌入任何地方

iframe + postMessage SDK。独立 UI 使用 Alpine.js(零构建)。适用于任何框架。

JWT认证 + 权限范围

每用户路径前缀、权限声明、磁盘白名单、仅所有者模式——也可从 viewer/editor/admin 角色预设开始。

ACL 角色预设

从 viewer/editor/admin/superadmin 预设中签发令牌——一个参数即可展开正确的权限、磁盘和作用域声明,无需手动拼装。

AI自动标签

Claude / OpenAI vision — 自动alt文本、标题、标签。

图片裁剪

内置裁剪工具,预设宽高比。

图片优化

自动WebP变体 — 缩略图、中等、大图。

预签名上传

浏览器直接上传到S3/R2 — 服务器零带宽消耗。

分片上传

S3 multipart,支持>10MB文件。

全文搜索

对文件名、标题、标签建立索引搜索——默认基于文件,也可选用自己的 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。

审计日志

记录所有写入操作。

速率限制

每用户令牌桶API保护。

存储配额

通过JWT claims设置每用户限制。

BYOB 存储桶

用户自带 S3/R2 — 凭证在 JWT 中加密(AES-256-GCM)。

重复检测

SHA-256 相同则跳过重复上传,除非强制覆盖。

SDK 令牌刷新

401 时 onTokenRefresh — 合并刷新、重试,以及 updateToken() 主动轮换。

存储桶体检

诊断任意 S3/R2 磁盘——凭证、读/写/删、预签名、CORS、分片——并给出可直接粘贴的 IAM 与 CORS 修复方案。几分钟接入 BYOB 存储桶。

SFTP 磁盘

继 S3/R2 之后的第三种驱动——把任意 VPS 或共享主机变成文件管理器。

代码 / 配置编辑器

在浏览器中编辑文本与配置文件(wp-config.php、.env、nginx.conf),类 cPanel。

压缩与解压

将选中项打包为 zip,或就地解压——已防 zip-slip 与压缩炸弹。

水印

实时叠加文字或 Logo 水印以保护预览——绝不修改原文件。

按需 WebP + AVIF

通过一个 URL 以缓存的 AVIF/WebP 提供任意尺寸图片(按 Accept 协商),附带响应式 srcset。

SFTP 权限

用类 cPanel 对话框更改 SFTP 磁盘上的 Unix 文件权限(chmod)。

SSH 终端

SFTP 磁盘上的无状态命令行终端——类 cPanel 的管理工具,内置且免费(也可嵌入自建的 ttyd 获得完整 PTY)。

一键 Git 部署

直接从文件管理器在 SFTP 服务器上拉取并重置 Git 仓库——固定形式,非任意 shell,默认关闭 hooks。

用量面板

一目了然的存储用量——配额加按类型和文件夹的细分。

媒体预览

内联预览图片、视频、音频与 PDF;私有本地媒体安全流式传输(支持 Range)。

快速安装

2分钟启动运行

composer require fluxfiles/fluxfiles
cp .env.example .env

# .env
FLUXFILES_SECRET=your-random-32-char-secret
FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com

require_once 'vendor/autoload.php';

$token = fluxfiles_token(
    userId: 'user-123',
    perms: ['read', 'write', 'delete'],
    disks: ['local', 's3', 'r2'],
    prefix: 'user-123/',
    maxUploadMb: 10,
    allowedExt: null,
    ttl: 3600
);
composer require fluxfiles/laravel
php artisan vendor:publish --tag=fluxfiles-config

# .env — point the adapter at your FluxFiles server
FLUXFILES_ENDPOINT=https://fm.yourdomain.com
FLUXFILES_SECRET=your-secret-min-32-chars

# Optional: match CORS on the FluxFiles host
# FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com

# Config: config/fluxfiles.php
npm install @fluxfiles/node

// 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)
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}
<!-- Demo: unpkg. In production, serve fluxfiles.js from your FluxFiles host -->
<script src="https://unpkg.com/fluxfiles@latest/fluxfiles.js"></script>

<script>
FluxFiles.open({
    endpoint: 'https://your-api.com',
    token: 'eyJhbGci...',
    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"
/>
git clone https://github.com/thai-pc/fluxfiles.git
docker build -f fluxfiles/docker/Dockerfile.prod -t fluxfiles fluxfiles

docker run -p 8080:80 \\
  -e FLUXFILES_SECRET=your-random-32-char-secret \\
  fluxfiles

# UI: http://localhost:8080/public/index.html
git clone https://github.com/thai-pc/fluxfiles.git
cd fluxfiles
composer install -d packages/core
cp .env.example .env

cd packages/core
php -S localhost:8080 router.php

# UI:  http://localhost:8080/public/index.html
# API: http://localhost:8080/api/fm/list?disk=local&path=

兼容

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

集成

适配你技术栈的即插即用适配器

官方适配器可将 FluxFiles 原生嵌入你已经在用的框架和编辑器中。

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

嵌入

几行代码即可嵌入

加载 fluxfiles.js,传入由服务端签发的 JWT,即可把完整的文件管理器(或文件选择弹窗)放进任意页面。

<script src="https://fm.example.com/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 + Local + SFTP
嵌入任何框架
JWT认证 + 权限范围
SEO元数据
AI自动标签
图片裁剪
分片上传
全文搜索
深色模式
16种语言
PHP ≥ 8.1
积极维护中
现代UI
能力 FluxFiles Filestack Uploadcare Cloudinary Supabase Storage
自托管(运行在你的基础设施)
BYOB——每个客户自有存储桶
可嵌入的文件管理器 UI
开源(MIT)
无按存储/上传的 SaaS 费用
多存储(S3 / R2 / 本地)
内置按租户令牌作用域

对比反映各产品的典型默认能力;每款产品在各自领域都很出色。FluxFiles 的定位是可嵌入、自托管、自带存储桶三者的组合。

对比数据截至 September 2026,非官方关联——如需纠正请前往 GitHub 仓库反馈。

常见问题

常见问题解答

身份验证如何工作?
无状态 JWT(HS256):你在服务端签发带有细粒度声明(权限、磁盘、路径范围、限额)的令牌,因此每个用户只能看到你允许的内容。
我的用户需要 FluxFiles 账号吗?
不需要。FluxFiles 信任你自己应用签发的 JWT,可直接接入你现有的认证——无需单独的用户系统。
运行它需要什么?
PHP 8.1+、几个常见扩展和 Composer。指向一个磁盘,设置密钥与允许来源,然后启动即可——在小型 VPS 上也能流畅运行。
不同用户可以拥有不同权限吗?
可以。你可以用细粒度的 claims(读/写/删除、磁盘、路径前缀、上传限制、允许的扩展名、owner-only)签发 token,也可以直接使用四种内置角色预设之一——viewer、editor、admin、superadmin——一行代码限定 token 范围,无需逐条罗列 claim。
我需要自己运行数据库吗?
不需要。默认情况下,所有元数据(文件信息、搜索索引、审计日志)都以 JSON 附属文件的形式存放在文件旁边——无需额外部署或备份。如果你更想把这些记录保存在自己的 MySQL、PostgreSQL 或 SQLite 中,可选的 FLUXFILES_STORAGE_BACKEND=db 模式会把它们迁移过去;无论哪种方式,文件本体始终留在你的存储中。
有使用限制吗?
核心本身没有人为设限——没有月活用户上限,也不会强制提示升级。你可以通过 JWT claims 自行设置限制:按用户的存储配额、上传大小/扩展名限制,以及内置的速率限制器(默认每分钟 60 次读取/10 次写入,可配置)。