Upload 作者:FriendsOfFlarum

一款为你的论坛智能处理文件上传的扩展。
功能
- 对于图片:
- Mime 类型到上传适配器的映射。
- Mime 类型白名单。
- 上传到不同的存储服务(例如本地、Imgur、AWS S3)。
- 拖拽上传。
- 同时上传多个文件(按钮和拖拽上传均支持)。
- 易于扩展,该扩展重度依赖事件(Events)。
- 用于禁用或强制使用特定适配器的扩展接口(见下文)
安装
手动安装:
composer require fof/upload:"*"
更新
composer require fof/upload:"*"
php flarum migrate
php flarum cache:clear
配置
启用扩展后,左侧将出现一个新选项卡。这个独立的设置页面允许你进一步配置此扩展。
在新安装中,系统会为你插入一个预定义的正则表达式,以启用图片上传,并限制为安全的图片类型。由于我们的 SVG 净化方法,我们现在将 SVG 包含在安全类型中。默认允许的图片类型有:
- JPEG
- PNG
- GIF
- WebP
- AVIF
- BMP
- TIFF
- SVG
这些类型的正则表达式是 ^image\/(jpeg|png|gif|webp|avif|bmp|tiff|svg\+xml)$,并且可以根据需要修改。我们强烈建议不要使用诸如 ^image\/.* 的通配符,因为这可能会在上传文件中引入漏洞。fof/upload 在 1.8.0 之前的版本默认使用此通配符,并被认为是不安全的。
请确保也在权限页面上配置上传权限。
存储配置
FoF Upload 支持通过管理面板(数据库设置)和环境变量两种方式进行配置。当配置了环境变量时,环境变量优先于数据库设置。
环境变量配置
你可以使用环境变量配置存储适配器,这在以下场景中特别有用:
- Docker/容器化部署
- CI/CD 流水线
- 多环境设置(开发/预发布/生产)
- 将凭证排除在数据库之外
AWS S3 / 兼容 S3 的存储
要通过环境变量配置 S3,请设置所有四个必需变量:
# 必需(4 项都必须设置)
FOF_UPLOAD_AWS_S3_KEY=你的访问密钥 ID
FOF_UPLOAD_AWS_S3_SECRET=你的秘密访问密钥
FOF_UPLOAD_AWS_S3_BUCKET=你的存储桶名称
FOF_UPLOAD_AWS_S3_REGION=us-east-1
# 可选
FOF_UPLOAD_AWS_S3_ACL=public-read # 对象 ACL (public-read, private 等)
FOF_UPLOAD_AWS_S3_ENDPOINT=https://s3.example.com # 用于兼容 S3 的服务 (MinIO, Wasabi 等)
FOF_UPLOAD_AWS_S3_PATH_STYLE_ENDPOINT=true # MinIO 及部分 S3 兼容服务必需
FOF_UPLOAD_AWS_S3_CUSTOM_URL=https://cdn.example.com # 存储桶的自定义域名
FOF_UPLOAD_CDN_URL=https://cdn.example.com # 用于提供文件服务的 CDN 地址
IAM 角色认证 (EC2/ECS/EKS):
对于拥有 IAM 角色的环境(EC2 实例、ECS 任务、EKS Pod),你可以省略凭证:
# IAM 模式必需
FOF_UPLOAD_AWS_S3_BUCKET=你的存储桶名称
FOF_UPLOAD_AWS_S3_REGION=us-east-1
FOF_UPLOAD_AWS_S3_USE_IAM=true # 启用 IAM 角色认证
# 可选(与上面相同)
FOF_UPLOAD_AWS_S3_ACL=public-read
FOF_UPLOAD_CDN_URL=https://cdn.example.com
当 FOF_UPLOAD_AWS_S3_USE_IAM=true 时,不需要凭证,AWS SDK 将自动使用实例/Pod 的 IAM 角色。
重要提示:
- 传统模式:所有 4 个变量 (
KEY, SECRET, BUCKET, REGION) 都必须设置
- IAM 模式:仅
BUCKET, REGION 和 USE_IAM=true 是必需的
- 如果缺少任何必需的变量,扩展将回退到数据库设置
- 当完全配置时,环境变量总是覆盖数据库设置
兼容 S3 的服务
LocalStack (本地开发):
FOF_UPLOAD_AWS_S3_KEY=test
FOF_UPLOAD_AWS_S3_SECRET=test
FOF_UPLOAD_AWS_S3_BUCKET=uploads
FOF_UPLOAD_AWS_S3_REGION=us-east-1
FOF_UPLOAD_AWS_S3_ENDPOINT=http://localhost:4566
FOF_UPLOAD_AWS_S3_PATH_STYLE_ENDPOINT=true # LocalStack 必需!
MinIO (自托管):
FOF_UPLOAD_AWS_S3_KEY=minioadmin
FOF_UPLOAD_AWS_S3_SECRET=minioadmin
FOF_UPLOAD_AWS_S3_BUCKET=uploads
FOF_UPLOAD_AWS_S3_REGION=us-east-1
FOF_UPLOAD_AWS_S3_ENDPOINT=https://minio.example.com
FOF_UPLOAD_AWS_S3_PATH_STYLE_ENDPOINT=true # MinIO 必需!
DigitalOcean Spaces:
FOF_UPLOAD_AWS_S3_KEY=你的 Spaces 密钥
FOF_UPLOAD_AWS_S3_SECRET=你的 Spaces 密钥
FOF_UPLOAD_AWS_S3_BUCKET=你的空间名称
FOF_UPLOAD_AWS_S3_REGION=nyc3
FOF_UPLOAD_AWS_S3_ENDPOINT=https://nyc3.digitaloceanspaces.com
Wasabi:
FOF_UPLOAD_AWS_S3_KEY=你的 Wasabi 密钥
FOF_UPLOAD_AWS_S3_SECRET=你的 Wasabi 密钥
FOF_UPLOAD_AWS_S3_BUCKET=你的存储桶
FOF_UPLOAD_AWS_S3_REGION=us-east-1
FOF_UPLOAD_AWS_S3_ENDPOINT=https://s3.wasabisys.com
Backblaze B2:
FOF_UPLOAD_AWS_S3_KEY=你的密钥 ID
FOF_UPLOAD_AWS_S3_SECRET=你的应用程序密钥
FOF_UPLOAD_AWS_S3_BUCKET=你的存储桶
FOF_UPLOAD_AWS_S3_REGION=us-west-004
FOF_UPLOAD_AWS_S3_ENDPOINT=https://s3.us-west-004.backblazeb2.com
使用 CDN 的本地存储
对于前端使用了 CDN 的本地存储:
FOF_UPLOAD_CDN_URL=https://cdn.example.com
配置优先级
- 环境变量(最高优先级——当所有必需变量都已设置时)
- 数据库设置(管理面板配置)
- 默认值(如果两者都未配置,则为空值)
Mime 类型正则表达式
正则表达式赋予你很大的自由度,但它们也非常难以理解。这里有一些提示,但欢迎在 Flarum 官方论坛上寻求帮助,或者查看 regex101.com,在那里你可以交互式地构建和测试你的正则表达式模式。
如果你想允许所有常规文件类型,包括视频、音乐、压缩文件和图片,请使用以下表达式:
(video\/(3gpp|mp4|mpeg|quicktime|webm))|(audio\/(aiff|midi|mpeg|mp4))|(image\/(gif|jpeg|png))|(application\/(x-(7z|rar|zip)-compressed|zip|arj|x-(bzip2|gzip|lha|stuffit|tar)|pdf))
一个 Mime 类型由主类型和子类型组成。例如,主类型可以是 image、video 和 application。
子类型则像一个更详细的规范,例如 png、pdf 等。这两者由 / 分隔,在正则表达式中,你必须使用 \/ 来转义此字符。
禁用或强制使用特定适配器
在某些情况下,你可能希望禁用某个适配器,或强制使用某个适配器。这在你根目录下的 extend.php 文件中设置。
例如,你可以禁用 imgur
(new FoF\Upload\Extend\Adapters())
->disable('imgur'),
也可以链式调用多个命令:
(new FoF\Upload\Extend\Adapters())
->disable('imgur')
->disable('aws-s3'),
你也可以强制使用一个适配器:
(new FoF\Upload\Extend\Adapters())
->force('imgur'),
当前可用的适配器名称:
命令
MapFilesCommand
使用 php flarum fof:upload 命令,你手中就有了一个强大的工具,可以将上传的文件映射到帖子并清理未使用的文件。为此,需要考虑两个步骤:
- 映射 (
--map) 允许你检查所有帖子,以确定哪些上传的文件在帖子中被使用过,并存储此信息
- 清理 (
--cleanup, --cleanup-before=yyyy-mm-dd) 使你能够删除在给定时间之前上传且未被映射到任何(现有)帖子的文件。
此命令的意图源于最初的概念:了解哪些上传文件被用在何处,并允许删除未使用的、陈旧的文件。你可以手动运行此命令,或将其作为计划任务(cronjob)运行。
示例 1;仅映射文件:
php flarum fof:upload --map
示例 2;映射并清理
php flarum fof:upload --map --cleanup --cleanup-before="a month ago"
当你对命令的操作方式满意后,可以附加 --force 标志,这样就无需确认操作:
php flarum fof:upload --map --cleanup --cleanup-before="last year" --force
当此命令被放入定期执行的计划任务中时,将会发生以下(总结的)事情:
- 根据计划任务的间隔(每天、每周或其他)
- 该命令将遍历所有上传文件,以发现它们在哪些帖子中被使用过
- 删除那些在 "去年" 上传但在帖子中未找到的文件
测试与安全措施
FoF Upload 包含自动化测试以确保:
✅ 有效文件成功上传
✅ 受限文件被阻止
✅ SVG 净化消除潜在的 XSS 风险
🔍 针对恶意文件的安全测试
我们专门测试以下情况:
- HTML 注入(伪装成图片的
.html 文件)
- MIME 欺骗(例如,包含脚本的
.png 文件)
- 多语言文件(作为两种不同格式运行的文件)
- SVG 净化(
<script>, <foreignObject>, 事件处理器, 外部样式等)
- ZIP 和 APK 处理(确保 APK 有效且 ZIP 不被错误分类)
提交额外的测试用例
我们欢迎社区对我们所有的扩展做出贡献!尤其是在涉及安全性的地方。如果你发现了新的边缘情况或能绕过验证的文件格式,请:
- 在 GitHub 上提交一个 issue
- 在
tests/ 目录下提交一个测试用例作为 PR
- 描述预期的行为(文件应该被接受吗?它应该被净化吗?)
🚀 这些测试确保了 FoF Upload 对所有 Flarum 用户保持安全和可靠!🚀
常见问题解答 (FAQ)
链接
一个由 FriendsOfFlarum 开发的扩展