제품 — FluxFiles
현대적인 파일 매니저에 필요한 모든 것
유연성이 필요한 개발자를 위해 구축.
멀티 스토리지
로컬, AWS S3, Cloudflare R2, SFTP — Flysystem v3. 설정만으로 전환.
어디든 임베드
iframe + postMessage SDK. 독립 UI는 Alpine.js(빌드 없음). 모든 프레임워크와 호환.
JWT 인증 + 스코핑
사용자별 경로 접두사, 권한, 디스크 화이트리스트, owner-only 모드 — 또는 viewer/editor/admin 역할 프리셋으로 시작.
ACL 역할 프리셋
viewer/editor/admin/superadmin 프리셋으로 토큰 발급 — 매개변수 하나로 올바른 권한·디스크·범위 클레임이 자동으로 구성되어 수동 조합이 필요 없습니다.
AI 자동 태그
Claude / OpenAI vision — alt 텍스트, 제목, 태그 자동 생성.
이미지 자르기
종횡비 프리셋이 있는 인라인 자르기 도구.
이미지 최적화
WebP 변형 자동 생성 — 썸네일, 중간, 대형.
사전 서명 업로드
브라우저에서 S3/R2로 직접 업로드 — 서버 대역폭 제로.
청크 업로드
10MB 초과 파일용 S3 멀티파트.
전체 텍스트 검색
이름, 제목, 태그 인덱스 검색 — 기본은 파일 기반, 선택적으로 자체 SQL 데이터베이스를 백엔드로 사용 가능.
DB 기반 메타데이터
선택적 FLUXFILES_STORAGE_BACKEND=db 모드 — 메타데이터, 검색/폴더 인덱스, 감사 로그가 JSON 사이드카 대신 자체 MySQL/PostgreSQL/SQLite에 저장됩니다. 파일 바이트는 두 경우 모두 스토리지에 그대로 남습니다.
일괄 작업
다중 선택 이동, 복사, 삭제, 다운로드.
크로스 디스크 전송
로컬 ↔ S3 ↔ R2 간 복사/이동.
휴지통
복구 가능한 삭제, 자동 정리.
SEO 메타데이터
제목, alt, 캡션, 태그 — 클라우드는 S3 객체 메타데이터, 로컬은 sidecar JSON. 전체 텍스트 검색.
다크 모드
UI 및 SDK에서 라이트/다크/자동.
16개 언어
기본 영어. SDK, URL (?locale=), FLUXFILES_LOCALE로 설정. 아랍어 RTL.
감사 로그
모든 쓰기 작업 기록.
속도 제한
사용자별 토큰 버킷 API 보호.
저장소 할당량
JWT 클레임을 통한 사용자별 제한.
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)을 브라우저에서 편집.
압축 & 해제
선택 항목을 zip으로 받거나 제자리에서 해제 — zip-slip·폭탄 방어.
워터마크
미리보기 보호를 위해 텍스트·로고 워터마크를 즉시 적용 — 원본은 그대로.
온디맨드 WebP + AVIF
하나의 URL로 모든 크기 이미지를 캐시된 AVIF/WebP로 제공(Accept 협상), 반응형 srcset 포함.
SFTP 권한
cPanel 스타일 대화상자로 SFTP 디스크의 유닉스 권한(chmod) 변경.
SSH 터미널
무료 terminal_pty_url 클레임으로 SFTP 디스크에서 직접 운영하는 ttyd / gotty / wetty를 앱 내 터미널로 임베드할 수 있습니다. FluxFiles는 자체 셸을 제공하지 않습니다.
원클릭 Git 배포
파일 관리자에서 바로 SFTP 서버의 Git 저장소를 pull·reset — 고정된 형태이며 임의 셸이 아니고, hooks는 기본적으로 꺼져 있습니다.
사용량 대시보드
스토리지를 한눈에 — 할당량과 유형별·폴더별 분석.
미디어 미리보기
이미지·동영상·오디오·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. 프로덕션 배포 시: 32바이트 이상의 FLUXFILES_SECRET과 FLUXFILES_ALLOWED_ORIGINS(또는 FLUXFILES_FRAME_ANCESTORS)를 설정하세요. 패키지 루트를 웹 문서 루트로 사용하고 nginx에서 /_fluxfiles/ 와 .env를 차단하세요. 메인 JWT를 URL에 넣지 마세요. 어댑터는 postMessage로 전달합니다. DEPLOYMENT.md
호환 프레임워크
통합
당신의 스택을 위한 드롭인 어댑터
공식 어댑터로 이미 사용 중인 프레임워크와 에디터에 FluxFiles를 네이티브로 임베드하세요.
CKEditor나 TinyMCE를 자신의 스토리지와 함께 사용하세요. CKBox나 Tiny Drive 구독이 필요 없습니다. FluxFiles는 파일을 찾아보고 삽입하는 툴바 버튼을 추가하며, 해당 제품들의 기능을 일대일로 대체하는 것은 아닙니다.
임베드
몇 줄이면 임베드 완료
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 | 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의 틈새는 임베드 가능·셀프 호스팅·자체 버킷의 조합입니다.
November 2026 기준 비교이며, 비공식 자료입니다 — 수정이 필요하면 GitHub 저장소에 알려주세요.
FAQ