基于 Docker 的轻量级 Web 文件管理器,Node.js 实现,极简依赖。
📦 Docker Hub 镜像: lagee/winfm 🔗 源码: GitHub | Gitee
- 📤 文件上传(拖拽 + 多文件 + 进度显示)
- 📁 新建 / 删除 / 重命名文件和文件夹
- ✂️📋 移动 / 复制文件(剪贴板式操作)
- 📦 批量选择、删除、移动、复制
- ⬇️ 单文件 / 批量下载(逐文件直传,不打包)
- 🔗 分享直链功能(生成文件直链地址,方便分享)
- 📊 目录大小异步计算(实时显示目录占用空间、文件和文件夹数量)
- 🌐 WebDAV 协议支持(内置 WebDAV 服务端,可被其他客户端挂载;也可挂载远端 WebDAV 服务器并在界面中浏览管理)
- 🖼️ 图片预览(PNG、JPG、GIF、SVG、WebP)
- 🎬 视频播放(MP4、WebM)
- 🎵 音频播放(MP3、WAV)
- 📄 文本 / 代码文件预览(支持多种编程语言高亮)
- 📑 PDF、Office 文档(Word、Excel、PowerPoint)
- 按名称 / 大小 / 修改时间排序(升序 / 降序)
- 文件夹优先分组显示
- 🍞 面包屑导航
- 📂 侧栏布局(包含目录树和常用目录书签,支持折叠/展开)
- 📱 响应式设计,完美支持移动端(操作收纳进「更多」菜单)
- 🎨 Material Design 3 橙色系主题(Material Web 组件 + Material Symbols 图标,自动适配深浅色,支持手动切换)
- 🔍 当前目录即时过滤搜索
- 🌐 组件与图标字体已内置本地化,离线 / 内网环境可用
- ⌨️ 快捷键支持(ESC 关闭弹窗,预览中左右方向键切换文件)
- 🖼️ 图片 / 视频缩略图自动生成(基于 sharp + ffmpeg,内存 LRU + 磁盘缓存)
- 📐 列表 / 网格视图切换,网格模式下以缩略图卡片展示媒体文件
- 路径遍历攻击防护
- 文件名安全验证
- 符号链接安全检查
- CSRF 跨站请求防护
- 管理员登录鉴权:首次访问引导设置账户,表单登录 + 签名会话 Cookie,管理操作与目录浏览均需登录
- 未登录匿名查看:保留单文件直链查看,按 IP 限制可访问的不同文件数并在空闲后失活
- 登录失败按 IP 限流,防暴力破解
# 直接拉取预构建镜像
docker pull lagee/winfm:latest
# 运行容器
docker run -d \
--name file-manager \
-p 8888:8888 \
-v /your/local/path:/data \
lagee/winfm:latest
# 访问
# http://localhost:8888创建 docker-compose.yml 文件:
services:
file-manager:
image: lagee/winfm:latest
container_name: file-manager
restart: unless-stopped
ports:
- "8888:8888"
volumes:
- /your/local/path:/data然后运行:
docker compose up -d# 克隆仓库
git clone https://github.com/lageev/winFM.git
# 或 Gitee
git clone https://gitee.com/fringhuang/win-fm.git
cd winFM
# 构建并启动
docker compose up -d
# 或者手动构建
docker build -t winfm .
docker run -d -p 8888:8888 -v /your/local/path:/data winfm编辑 docker-compose.yml 修改挂载目录:
services:
file-manager:
image: lagee/winfm:latest
container_name: file-manager
restart: unless-stopped
ports:
- "8888:8888"
volumes:
- /your/local/path:/data # 将本地目录映射到容器内 /data端口默认 8888,可在 docker-compose.yml 中修改:
ports:
- "8080:8888" # 改为 8080 端口使用 .env 文件配置本地路径,方便不同环境使用不同配置:
# 复制模板并修改
cp .env.example .env编辑 .env 文件:
# 数据目录的本地路径
DATA_DIR=/your/local/pathdocker-compose.yml 中使用 ${DATA_DIR} 引用:
volumes:
- ${DATA_DIR}:/data注意:
.env文件已被.gitignore忽略,不会同步到远程仓库。
凭据来源优先级:环境变量 > 持久化文件 > 未配置(首次引导)。
- 首次引导:不配置
FM_PASS时,首次访问会自动跳转到设置页/__fm/setup,在线设置管理员用户名与密码。设置后凭据(密码经 scrypt 哈希)与会话密钥持久化到数据目录的.fm-auth.json,立即生效并自动登录,重启后仍有效。 - 环境变量配置(跳过引导):
environment:
- FM_USER=admin # 管理员用户名,默认 admin
- FM_PASS=yourpassword # 管理员密码
- FM_SECRET=random-long-str # 会话签名密钥,建议设置以持久化登录态
- FM_SESSION_HOURS=168 # 可选,会话有效期(小时),默认 7 天
- FM_OPEN=1 # 可选,完全公开、无需登录并跳过引导- 仅单一管理员账户;访问目录或管理页面会跳转到登录页
/__fm/login,右上角可退出登录。 - 用环境变量配置且未设
FM_SECRET时密钥随机生成,服务重启后需重新登录(引导页设置的密钥会持久化,无此问题)。 - 兼容旧格式:
FM_AUTH=admin:yourpassword(等价于FM_USER+FM_PASS)。
开启鉴权后,未登录用户仍可通过直链查看单个文件(用于对外分享),但受配额限制;目录浏览与所有写操作仍需登录:
environment:
- FM_ANON=1 # 1 开启(默认),0 关闭后所有访问都需登录
- FM_ANON_LIMIT=20 # 时效内每个 IP 可查看的不同文件数上限
- FM_ANON_IDLE_MIN=30 # 空闲多少分钟后额度失活并重置- 同一文件重复访问、断点续传不重复计数;不同文件累计达到上限后返回
429。 - 空闲超过
FM_ANON_IDLE_MIN后该 IP 的额度失活并重新计算。
开启鉴权后,登录管理员可在文件的"分享"对话框为单个文件生成签名分享链接,并自定义:
- 查看次数:填 0 表示不限,达到上限后链接失效。
- 有效期(小时):填 0 表示永久,超时后链接失效。
链接形如 /__fm/s?t=<签名token>,凭链接无需登录即可查看该文件;token 经 HMAC 签名不可篡改,有效期由签名保证、服务重启后仍有效(查看次数计数为内存态,重启会重置)。
winFM 同时支持两个方向的 WebDAV:
1. 作为 WebDAV 服务端(让别的客户端挂载本机数据目录)
服务端入口固定为 /__dav/,即把数据目录通过 WebDAV 暴露出去。客户端地址形如:
http://你的地址:8888/__dav/
- 鉴权:复用管理员账户,采用 HTTP Basic 认证(用户名/密码与登录一致)。
FM_OPEN=1开放模式下无需认证。 - 支持的方法:
OPTIONS / PROPFIND / GET / HEAD / PUT / DELETE / MKCOL / COPY / MOVE / LOCK / UNLOCK / PROPPATCH,覆盖常见客户端(Windows 映射网络驱动器、macOS 访达「连接服务器」、RaiDrive、各类手机文件管理 App 等)的读写需求。 - 安全:内部配置文件(
.fm-auth.json、.fm-mounts.json等)不会出现在 WebDAV 列表中,也禁止直接访问。
2. 作为 WebDAV 客户端(挂载别的 WebDAV 服务器)
在侧栏「WebDAV 挂载」中点击「添加挂载」,填写名称、远端地址(http(s)://...)以及可选的用户名/密码后保存,即可像浏览本地目录一样在 winFM 界面里浏览、上传、下载、新建、重命名、删除远端文件。
- 挂载配置持久化在数据目录的
.fm-mounts.json(含远端凭据,文件权限0600,列表中隐藏且禁止访问)。 - 进入挂载后,面包屑以挂载点为根;移动/复制目前仅支持同一挂载内部(暂不支持本地与远端之间互相移动/复制)。
- 挂载管理与浏览均需管理员登录。
如果你需要保留本地特定的配置(如挂载路径、端口等),可以创建本地配置文件:
# 复制配置文件为本地版本
cp docker-compose.yml docker-compose.local.yml
cp watch-deploy.ps1 watch-deploy.local.ps1然后编辑 docker-compose.local.yml 修改为你本地的路径:
services:
file-manager:
image: lagee/winfm:latest
container_name: file-manager
restart: unless-stopped
ports:
- "8888:8888"
volumes:
- D:/your/local/path:/data # 修改为你本地的路径使用本地配置运行:
# 使用本地配置文件启动
docker compose -f docker-compose.local.yml up -d
# 使用本地监控脚本
.\watch-deploy.local.ps1注意:
*.local.yml和*.local.ps1文件已被.gitignore忽略,不会同步到远程仓库。
容器以非 root 用户 nodejs(uid=1001) 运行。如果挂载的目录中存在由其他工具(如 Syncthing、Samba 等)创建的子目录,这些目录可能属于 root 且权限为 755,导致无法上传文件。
症状: 根目录可上传,但某些子目录上传失败。
解决方法: 在宿主机上修复权限:
# Linux/Mac
chmod -R 777 /your/local/path
# Windows (在容器内执行)
docker exec -u root file-manager chmod -R 777 /data/或者,在 docker-compose.yml 中以 root 用户运行(简单但安全性稍低):
services:
file-manager:
image: lagee/winfm:latest
container_name: file-manager
restart: unless-stopped
user: "0:0" # 以 root 运行
ports:
- "8888:8888"
volumes:
- ${DATA_DIR}:/data- 运行时: Node.js 20 (Alpine)
- 依赖: busboy(流式上传解析)、sharp(图片缩略图)、ffmpeg(视频抽帧)
- UI 组件: Material Web(Material Design 3,已打包内置,无 CDN 依赖)
- 图标: Material Symbols(内置字体子集)
- 样式: Material Design 3 设计令牌(原生 CSS,运行时无构建步骤)
- 传输: HTML gzip 压缩、静态资源强缓存、文件 ETag/304、Range 断点续传
| 类型 | 扩展名 |
|---|---|
| 图片 | PNG、JPG、JPEG、GIF、SVG、WebP、AVIF、BMP、TIFF、ICO |
| 视频 | MP4、WebM、MKV、MOV、M4V |
| 音频 | MP3、WAV、OGG、AAC、FLAC、M4A、WMA、OPUS |
| 文档 | PDF、DOC、DOCX、XLS、XLSX、PPT、PPTX、CSV |
| 压缩包 | ZIP、RAR、7Z、TAR、GZ、TGZ、BZ2、XZ、ZST |
| 代码 | HTML、CSS、JS、TS、JSX、TSX、Vue、Svelte、Python、Java、C/C++、Go、Rust、Ruby、PHP、Swift、Kotlin 等 |
| 其他 | TXT、MD、YAML、TOML、XML、LOG、Shell 脚本、字体文件 |
- 上传文件: 点击上传按钮或直接拖拽文件到页面
- 新建文件夹: 点击文件夹图标按钮
- 批量操作: 勾选多个文件后使用底部操作栏
- 排序: 点击表头的名称、大小、时间进行排序
- 预览: 点击文件名旁的眼睛图标
- 下载: 点击下载图标,或批量选择后逐个下载(文件夹请进入后再选择文件)
- 分享直链: 点击文件操作列的分享图标,复制文件直链地址
- 侧栏导航: 点击左上角菜单图标展开侧栏,查看目录树和常用目录书签
- 目录大小: 页面顶部统计栏异步显示当前目录占用空间
MIT License
