Skip to content

devmc12/FlareDrive

 
 

Repository files navigation

FlareDrive

面向 Cloudflare R2 的轻量级、自托管文件管理器。FlareDrive 使用 React 与 Vite 提供 Web 文件管理界面,通过 Cloudflare Pages Functions 暴露 WebDAV API,并将文件存储在 R2 中;需要网页登录时,可选用 D1 保存会话。

Cloudflare 免费额度包含 10 GB R2 存储空间和每天 100,000 次 Pages Functions 调用。查看官方价格

简体中文 | English

功能亮点

文件管理

  • 网格和详细信息两种视图,支持按名称、修改时间、类型和大小排序或分组
  • 搜索、面包屑导航以及与浏览器前进/后退同步的目录 URL Hash
  • 桌面端框选、Ctrl/Cmd 多选、Shift 范围选择和右键菜单
  • 移动、复制、重命名、删除、批量下载和复制文件链接
  • 文件夹递归复制、移动和删除,支持将文件直接拖入目标文件夹

上传与缩略图

  • 上传单个或多个文件、整个文件夹,以及拖放文件或文件夹
  • 移动设备支持拍照上传和选择图片或视频
  • 大文件自动使用 R2 Multipart Upload;上传队列支持进度、取消和失败状态
  • 图片、视频和 PDF 上传时生成内容哈希缩略图,并存入隐藏的内部命名空间

预览与编辑

  • 图片缩放查看,浏览器原生音频、视频和 PDF 查看
  • 文本、Markdown 和 HTML 在线编辑、另存为及保存回 R2
  • Markdown 提供预览、分栏和编辑模式;HTML 在 sandbox iframe 中预览
  • ZIP 压缩包内容列表和单文件下载
  • DOCX、PPTX、XLSX、XLS 和 CSV 在独立 sandbox iframe 中本地渲染
  • Office 渲染器按格式延迟加载,打开一种格式不会加载另外两种格式的依赖

访问控制

  • 标准 WebDAV Basic Auth 管理员账号
  • 可选的单账号密码登录、D1 Session 和“退出所有设备”
  • 可选 Cloudflare Turnstile,只保护密码登录接口
  • WebDAV 范围令牌,支持只读 ro、读写 rw 和仅上传 up
  • 可选公开读取,仅开放 GETHEADPROPFIND

界面预览

文件管理与多选

FlareDrive file management

Markdown 编辑与预览

FlareDrive Markdown editor

ZIP 文件预览

FlareDrive ZIP preview

系统架构

flowchart LR
  Browser["Web 应用<br/>React + Vite"]
  WebDAV["/webdav/*<br/>Pages Functions"]
  Auth["/api/auth/*<br/>Pages Functions"]
  R2["R2 Bucket<br/>BUCKET"]
  D1["D1 会话库<br/>AUTH_DB,可选"]
  Office["Office 预览 iframe<br/>opaque origin"]

  Browser -->|WebDAV 请求| WebDAV
  WebDAV --> R2
  Browser -->|密码登录| Auth
  Auth --> D1
  Browser -. "MessageChannel 传输 ArrayBuffer" .-> Office
Loading

主页面先通过已认证的 /webdav 请求下载 Office 文件,再使用一次性 MessageChannelArrayBuffer 传入 iframe。iframe 只包含 sandbox="allow-scripts",没有 allow-same-origin;sandbox 与 CSP 共同禁止网络请求、表单、弹窗、对象、子框架和顶层导航。

主要技术组件:

层级 实现
Web 前端 React 19、MUI 9、Vite 8、TypeScript
API Cloudflare Pages Functions / Workers Runtime
文件存储 Cloudflare R2
登录会话 Cloudflare D1,可选
文档预览 Viewer.js、PDF.js、docx-preview、pptx-preview、SheetJS、Univer

部署到 Cloudflare Pages

前置条件

  • Cloudflare 账号
  • 一个 R2 存储桶
  • 一个与 Cloudflare Pages 连接的 Git 仓库或 Wrangler CLI

Pages 构建设置

将 fork 或克隆后的仓库连接到 Cloudflare Pages,并使用以下设置:

设置
Framework preset None
Build command npm run build
Build output directory build
Root directory 仓库根目录

Cloudflare 绑定

部署前至少配置 R2 绑定:

类型 绑定名称 是否必需 用途
R2 Bucket BUCKET 存储文件和内部缩略图
D1 Database AUTH_DB 仅 Password 模式 保存登录 Session 的哈希和过期时间

配置绑定和环境变量后重新部署。public/_routes.json 只将 /webdav/*/api/auth/* 交给 Pages Functions,其他路径作为静态资源提供。

最小 Basic Auth 配置

默认认证模式是 basic。设置:

FLAREDRIVE_AUTH_MODE="basic"
WEBDAV_USERNAME="admin"
WEBDAV_PASSWORD="replace-with-a-strong-password"

首次访问 WebDAV 时,浏览器或 WebDAV 客户端会显示 HTTP Basic Auth 登录提示。

使用 Wrangler 部署

npm ci
npm run build
npx wrangler pages deploy build --project-name <your-pages-project>

认证与访问控制

模式对比

模式 Web 应用 WebDAV 客户端 主要配置
basic 依赖浏览器 HTTP Basic Auth 管理员账号或范围令牌 WEBDAV_USERNAMEWEBDAV_PASSWORD
password 登录对话框、D1 Session Cookie 仍使用管理员 Basic Auth 或范围令牌 AUTH_DBFLAREDRIVE_LOGIN_ACCOUNTFLAREDRIVE_LOGIN_PRIVATE_KEY
Public Read 无认证读取列表和文件 无认证读取 WEBDAV_PUBLIC_READ="1"

Password 模式只提供一个网页登录账号。WebDAV 客户端继续使用 WEBDAV_USERNAMEWEBDAV_PASSWORD 或范围令牌。

配置 Password 模式

  1. 创建 D1 数据库,并绑定为 AUTH_DB
  2. 执行 Session Schema:
npx wrangler d1 execute <database-name> --remote --file migrations/0001_auth_sessions.sql
  1. 生成密码的 SHA-256:
node -e "const crypto=require('crypto'); console.log(crypto.createHash('sha256').update(process.argv[1]).digest('hex'))" "replace-with-a-strong-password"
  1. 生成 ECDH P-256 私钥:
node -e "const { webcrypto } = require('crypto'); (async () => { const pair = await webcrypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveKey']); console.log(JSON.stringify(await webcrypto.subtle.exportKey('jwk', pair.privateKey))); })()"
  1. 配置以下变量:
FLAREDRIVE_AUTH_MODE="password"
FLAREDRIVE_LOGIN_ACCOUNT='{"username":"admin","password":"<sha256-hex>"}'
FLAREDRIVE_LOGIN_PRIVATE_KEY='<private-jwk-json>'

网页登录载荷使用临时客户端 ECDH P-256 密钥协商 AES-GCM 密钥后加密。登录成功后,服务端设置不透明的 HttpOnlySameSite=Lax Session Cookie;HTTPS 请求还会设置 Secure。D1 只保存 Session Token 的 SHA-256,不保存原始 Token。

启用 Turnstile

同时配置以下两个值,Password 登录接口才会要求 Turnstile:

FLAREDRIVE_TURNSTILE_SITE_KEY="<turnstile-site-key>"
FLAREDRIVE_TURNSTILE_SECRET_KEY="<turnstile-secret-key>"

Turnstile 不保护 WebDAV Basic Auth,也不会改变范围令牌行为。

WebDAV 范围令牌

先为每个原始 Token Secret 生成 SHA-256,然后将哈希写入 WEBDAV_ACCESS_TOKENS

WEBDAV_ACCESS_TOKENS='[{"username":"phone","password":"<sha256-hex>","access":"rw","includes":["photos/phone/"],"excludes":["photos/phone/private/"]},{"username":"dropbox","password":"<sha256-hex>","access":"up","includes":["uploads/"],"excludes":[]}]'
access 允许的操作
ro GETHEADPROPFIND
rw 所有受支持的 WebDAV 和分片上传操作
up 文件 PUT、分片创建/上传/完成以及分片中止;不能读取、列目录、建目录、复制、移动或删除已有文件

includesexcludes 使用 R2 对象键路径,而不是完整 URL。范围允许路径本身和其子路径;例如 photos/phone 不会匹配 photos/phonebookexcludes 优先于 includesCOPYMOVE 的目标也必须位于允许范围内。

WebDAV 客户端登录时输入 Token 的 username原始 Token Secret,不是配置中的 SHA-256。范围客户端应直接连接到其允许前缀,例如:

https://<your-domain>/webdav/photos/phone/

up Token 无法创建父目录,因此目标父目录必须已存在;直接上传到存储桶根目录时除外。

绑定和环境变量参考

名称 类型 默认值 说明
BUCKET R2 绑定 主文件存储,必需
AUTH_DB D1 绑定 Password 模式 Session 数据库
FLAREDRIVE_AUTH_MODE 变量 basic basicpassword
WEBDAV_USERNAME Secret/变量 WebDAV 管理员用户名
WEBDAV_PASSWORD Secret WebDAV 管理员密码
WEBDAV_ACCESS_TOKENS Secret 范围令牌 JSON 数组
WEBDAV_PUBLIC_READ 变量 未启用 设置为 1 时公开 GETHEADPROPFIND
FLAREDRIVE_LOGIN_ACCOUNT Secret 单账号用户名和密码哈希 JSON
FLAREDRIVE_LOGIN_PRIVATE_KEY Secret Password 登录使用的 ECDH P-256 私有 JWK
FLAREDRIVE_TURNSTILE_SITE_KEY 变量 Turnstile 前端 Site Key
FLAREDRIVE_TURNSTILE_SECRET_KEY Secret Turnstile 服务端 Secret Key
FLAREDRIVE_SESSION_TTL_SECONDS 变量 86400 普通登录有效期
FLAREDRIVE_REMEMBER_TTL_SECONDS 变量 604800 “保持登录”有效期

生产密钥应使用 Cloudflare Secret 或受保护的环境变量,不要写入 Git。

本地开发

安装与配置

npm ci

复制本地配置模板:

# Windows PowerShell
Copy-Item .dev.vars.example .dev.vars
# macOS / Linux
cp .dev.vars.example .dev.vars

编辑 .dev.vars。使用 Basic 模式时无需初始化 D1;使用 Password 模式时执行:

npx wrangler d1 execute AUTH_DB --local --config wrangler.local.jsonc --file migrations/0001_auth_sessions.sql

启动前后端:

npm run dev
服务 地址 说明
Vite http://127.0.0.1:3601 前端、HMR,并代理 /webdav/api
Wrangler Pages Dev http://127.0.0.1:3602 Pages Functions、Local R2 和 Local D1

打开 http://127.0.0.1:3601。Basic 模式下,前端不会把开发账号直接写入请求头;浏览器在 /webdav/ 返回认证挑战时要求输入凭据。

构建与预览

npm run build
npm run preview

npm run previewhttp://127.0.0.1:3600 只预览已经构建的静态前端,不会启动 Pages Functions。

常用命令

命令 作用
npm run dev 同时启动 Vite 和本地 Pages Functions
npm run dev:frontend 只启动 Vite,端口 3601
npm run dev:functions 只启动 Wrangler Pages Dev,端口 3602
npm run build TypeScript 类型检查并生成生产构建到 build/
npm run preview 预览 build/ 中的静态前端
npm run lint 检查 src/functions/ 和构建配置

WebDAV 客户端

管理员端点:

https://<your-domain>/webdav/

支持的方法:OPTIONSPROPFINDMKCOLHEADGETPOSTPUTCOPYMOVEDELETE。其中 POST 及带查询参数的部分 PUT/DELETE 用于 Web 应用的 R2 Multipart Upload 流程。

Web 应用对小于 100,000,000 字节的文件使用普通 PUT,达到该值时切换到自定义分片上传。普通 WebDAV 客户端通常只使用标准 PUT,不会自动使用 FlareDrive 的分片 API;上传大文件时建议使用 Web 应用。

Basic Auth 会在每次请求中发送 Base64 编码的账号密码。Base64 不是加密,请始终通过 HTTPS 使用生产站点。

预览支持与限制

类型 行为 浏览器内大小限制
图片 Viewer.js 缩放查看 未设置专用限制
音频 / 视频 浏览器原生播放器 未设置专用限制
PDF 新窗口使用浏览器查看;PDF.js 用于生成缩略图 未设置专用限制
文本 / Markdown / HTML 预览、编辑、保存和另存为 2 MiB
ZIP 文件列表和单文件下载 30 MiB
DOCX / PPTX / XLSX / XLS / CSV sandbox iframe 内本地解析和渲染 小于 10 MiB

Office 预览以兼容和快速浏览为目标,复杂字体、动画、宏、嵌入对象或高级公式不保证与桌面 Office 完全一致。项目不会执行 Office 宏。

安全设计

  • Office 和 HTML 预览运行在没有 allow-same-origin 的 sandbox iframe 中;Office iframe 的 sandbox 与 CSP 禁止网络、表单、对象、嵌套 iframe、弹窗和顶层导航;DOCX 额外禁用 altChunk HTML,并在渲染完成后移除链接和导航能力;Markdown 渲染则跳过原始 HTML
  • 上传或下载 HTML、SVG、XHTML 等活动内容时,WebDAV 强制附件响应、nosniff 和 sandbox CSP
  • 内部 _$flaredrive$/ 命名空间不会出现在普通目录列表,并限制为受控缩略图操作
  • Password 模式只在 D1 存储 Session Token 哈希
  • 范围令牌会校验源路径、COPY/MOVE 顶层目标及每个递归派生目标

本项目当前是单账号文件管理器,不包含多租户权限模型、操作审计日志或恶意文件扫描。

项目结构

index.html                     Vite 主入口
office-preview.html            隔离的 Office iframe 入口
src/                           React Web 应用
src/office-preview/            DOCX、PPTX、Spreadsheet iframe 运行时
functions/webdav/              WebDAV Pages Functions 和方法处理器
functions/api/auth/            Password Session API
functions/auth.ts              登录、Turnstile、Cookie 和 D1 Session 工具
migrations/                    D1 Schema
public/_headers                Office iframe CSP 和静态资源 CORS
public/_routes.json            Pages Functions 路由范围
vite.config.ts                 Vite、代理、Worker 和预览分包配置

已知边界

  • Password 模式只支持一个配置账号,不是多用户网盘
  • Public Read 会让任何访问者无需认证即可列出和读取允许的 WebDAV 内容
  • 大目录的递归复制、移动和删除会产生多次 R2 操作

致谢

许可证

MIT

About

Cloudflare R2 file hosting with WebUI, supporting WebDAV (optional scoped access tokens) or secure session login, with online preview and editing.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 99.1%
  • Other 0.9%