FriendsOfFlarum 出品的 Upload 扩展

一个智能处理论坛文件上传的扩展。
功能特性
- 图片方面:
- MIME 类型到上传适配器的映射。
- MIME 类型白名单。
- 支持不同的存储服务(例如本地、Imgur、AWS S3)。
- 拖放上传。
- 一次上传多个文件(按钮和拖放都支持)。
- 易于扩展,扩展高度依赖事件系统。
- 扩展器接口可禁用或强制使用特定适配器(见下文)
安装
手动安装:
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=your-access-key
FOF_UPLOAD_AWS_S3_SECRET=your-secret-key
FOF_UPLOAD_AWS_S3_BUCKET=your-bucket-name
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 URL
IAM 角色认证(EC2/ECS/EKS):
对于使用 IAM 角色的环境(EC2 实例、ECS 任务、EKS Pod),可以省略凭据:
# IAM 模式必需
FOF_UPLOAD_AWS_S3_BUCKET=your-bucket-name
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=your-spaces-key
FOF_UPLOAD_AWS_S3_SECRET=your-spaces-secret
FOF_UPLOAD_AWS_S3_BUCKET=your-space-name
FOF_UPLOAD_AWS_S3_REGION=nyc3
FOF_UPLOAD_AWS_S3_ENDPOINT=https://nyc3.digitaloceanspaces.com
Wasabi:
FOF_UPLOAD_AWS_S3_KEY=your-wasabi-key
FOF_UPLOAD_AWS_S3_SECRET=your-wasabi-secret
FOF_UPLOAD_AWS_S3_BUCKET=your-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=your-key-id
FOF_UPLOAD_AWS_S3_SECRET=your-application-key
FOF_UPLOAD_AWS_S3_BUCKET=your-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)允许你删除在指定时间之前上传且尚未映射到任何(现有)帖子的文件
此命令的意图源于理解上传文件在何处使用的基本概念,并允许删除未使用的陈旧文件。你可以手动运行此命令,也可以将其设置为定时任务。
示例 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 上提出问题
- 在
tests/ 目录下提交一个 PR 测试用例
- 描述预期行为(文件应该被接受还是应该被清理?)
🚀 这些测试确保 FoF Upload 对所有 Flarum 用户保持安全和可靠!🚀
常见问题
链接
由 FriendsOfFlarum 开发的扩展