Skip to content

7.2 上传配置详解 ​

概述

文件上传配置定义在 config/file.php 和 .env 中,控制上传目录、域名、大小限制、允许的文件类型等。所有值通过 env() 函数从 .env 文件读取,支持多环境切换。

配置文件 ​

php
// config/file.php — 文件上传配置
// 所有值通过 env() 函数从 .env 文件读取,支持多环境切换
return [
    'upload_dir' => env('file.upload_dir', ''),       // 上传根目录(绝对路径)
    'domain_url' => env('file.domain_url', ''),       // 文件访问域名(拼接完整 URL 用)
    'temp_dir'   => 'temp',                            // 临时目录名(相对 upload_dir)
    'image_ext'  => env('file.image_ext', 'gif,jpg,jpeg,png,bmp,webp,svg'),  // 允许的图片后缀
    'file_ext'   => env('file.file_ext', 'gif,jpg,jpeg,png,bmp,webp,svg,doc,docx,xls,xlsx,ppt,pptx,pdf,zip,rar,txt,csv,mp3,mp4,sql,js,css'),  // 允许的文件后缀
    'max_size'   => env('file.max_size', 10) * 1024 * 1024,  // 最大大小(MB → 字节)
];

配置项详解 ​

配置项.env 变量默认值说明
upload_dir[FILE] UPLOAD_DIR-上传根目录(绝对路径),所有文件存储于此
domain_url[FILE] DOMAIN_URL-文件访问域名,用于拼接完整 URL
temp_dir-temp临时目录名(相对 upload_dir)
image_ext[FILE] IMAGE_EXTgif,jpg,jpeg,png,bmp,webp,svg图片允许后缀
file_ext[FILE] FILE_EXT多种后缀文件允许后缀
max_size[FILE] MAX_SIZE10单文件最大大小(MB)

upload_dir — 上传根目录 ​

ini
; .env
[FILE]
UPLOAD_DIR = D:/uploads/rxthinkcmf

要求:

  • 必须是绝对路径
  • 目录必须存在且有写入权限
  • 生产环境建议放在项目目录外(防止被 Web 直接访问)

各环境示例:

环境路径示例
Windows 开发D:/uploads/rxthinkcmf
Linux 开发/home/www/uploads/rxthinkcmf
Linux 生产/data/uploads/rxthinkcmf
Docker/uploads/rxthinkcmf(挂载卷)

domain_url — 文件访问域名 ​

ini
; .env
[FILE]
DOMAIN_URL = https://cdn.example.com

要求:

  • 不要以 / 结尾
  • 必须是前端可访问的域名
  • 本地开发可留空(使用相对路径)

各环境示例:

环境域名示例
本地开发(留空,使用相对路径)
测试环境https://test-cdn.example.com
生产环境https://cdn.example.com
对象存储https://bucket-name.oss-cn-hangzhou.aliyuncs.com

max_size — 文件大小限制 ​

ini
; .env
[FILE]
MAX_SIZE = 10

单位: MB(配置文件中会自动转换为字节:10 * 1024 * 1024)

建议值:

场景建议值说明
头像上传2 MB图片通常不会太大
文章封面5 MB压缩后的图片
通用文件上传10 MB默认值
文档上传20 MBPDF/Word 等
视频上传100 MB需配合分片上传

image_ext — 图片允许后缀 ​

ini
; .env
[FILE]
IMAGE_EXT = gif,jpg,jpeg,png,bmp,webp,svg

默认值: gif,jpg,jpeg,png,bmp,webp,svg

说明: 用于 uploadFile?type=image 接口,只允许图片格式上传。

file_ext — 文件允许后缀 ​

ini
; .env
[FILE]
FILE_EXT = gif,jpg,jpeg,png,bmp,webp,svg,doc,docx,xls,xlsx,ppt,pptx,pdf,zip,rar,txt,csv,mp3,mp4,sql,js,css

默认值: 包含图片、文档、压缩包、音视频等常见格式。

说明: 用于 uploadFile 接口,允许所有合法文件格式。

.env 配置示例 ​

开发环境 ​

ini
[FILE]
UPLOAD_DIR = D:/uploads/rxthinkcmf
DOMAIN_URL =
MAX_SIZE = 10

测试环境 ​

ini
[FILE]
UPLOAD_DIR = /home/www/uploads/rxthinkcmf
DOMAIN_URL = https://test-cdn.example.com
MAX_SIZE = 10

生产环境 ​

ini
[FILE]
UPLOAD_DIR = /data/uploads/rxthinkcmf
DOMAIN_URL = https://cdn.example.com
MAX_SIZE = 10
IMAGE_EXT = jpg,jpeg,png,gif,bmp,webp
FILE_EXT = jpg,jpeg,png,gif,bmp,webp,doc,docx,xls,xlsx,pdf,zip,rar

对象存储(OSS) ​

ini
; 如果使用阿里云 OSS 等对象存储,domain_url 设为 OSS 域名
[FILE]
UPLOAD_DIR = /data/uploads/rxthinkcmf
DOMAIN_URL = https://your-bucket.oss-cn-hangzhou.aliyuncs.com
MAX_SIZE = 50

目录结构 ​

text
{upload_dir}/                          # upload_dir(上传根目录)
├── temp/                              # 临时目录(temp_dir)
│   └── 20260920/                      # 按日期分目录
│       ├── a1b2c3d4e5f6.jpg          # 随机文件名(防止冲突)
│       └── f6e5d4c3b2a1.png
├── article/                           # 正式目录(由 fileSaveDir 配置)
│   └── 20260920/
│       └── 143052_xK7pMn3q.jpg
├── example/
│   └── 20260920/
├── user/
│   └── avatar/
│       └── 20260920/
└── file_template/
    └── 20260920/

目录命名规则 ​

目录说明示例
temp/临时文件目录上传后暂存于此
{module}/正式目录(按模块)由 Logic 的 fileSaveDir 配置
{date}/日期子目录20260920(自动创建)
{random}.{ext}随机文件名a1b2c3d4e5f6.jpg(防止冲突)

文件生命周期 ​

text
1. 前端上传 → upload_file()
   保存到: {upload_dir}/temp/20260920/a1b2c3d4e5f6.jpg
   返回: https://cdn.example.com/temp/20260920/a1b2c3d4e5f6.jpg

2. 前端提交表单 → 携带 fileUrl
   POST /api/example/add { name: "测试", avatar: "https://..." }

3. BaseLogic::add() → save_file()
   检测到 temp/ → 移动到正式目录
   {upload_dir}/temp/20260920/a1b2c3d4e5f6.jpg
   → {upload_dir}/example/20260920/a1b2c3d4e5f6.jpg
   返回相对路径入库: /uploads/example/20260920/a1b2c3d4e5f6.jpg

4. BaseLogic::detail() → get_file_url()
   相对路径 → 拼接域名
   /uploads/example/20260920/a1b2c3d4e5f6.jpg
   → https://cdn.example.com/uploads/example/20260920/a1b2c3d4e5f6.jpg

与 Logic 层的配合 ​

php
class ArticleLogic extends BaseTenantLogic
{
    /**
     * 需要自动处理的文件上传字段
     *
     * @var array
     */
    protected array $fileFields = ['cover'];

    /**
     * 文件保存的子目录
     *
     * @var string
     */
    protected string $fileSaveDir = 'article';
}

实际路径映射:

text
配置:
  upload_dir = /data/uploads/rxthinkcmf
  fileSaveDir = article

结果:
  临时文件: /data/uploads/rxthinkcmf/temp/20260920/abc.jpg
  正式文件: /data/uploads/rxthinkcmf/article/20260920/abc.jpg
  数据库存: /uploads/article/20260920/abc.jpg
  前端显示: https://cdn.example.com/uploads/article/20260920/abc.jpg

Nginx 配置 ​

静态文件直接由 Nginx 返回 ​

nginx
# 配置 Nginx 直接处理文件请求,不经过 PHP
location /uploads/ {
    alias /data/uploads/rxthinkcmf/;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

禁止上传目录执行 PHP ​

nginx
# 安全:禁止上传目录执行 PHP 文件
location ~* /uploads/.*\.php$ {
    deny all;
}

禁止访问隐藏文件 ​

nginx
location ~ /\. {
    deny all;
}

常见问题 ​

问题 1:上传提示"目录不可写" ​

原因: upload_dir 目录没有写入权限。

解决:

bash
# Linux
chmod -R 755 /data/uploads/rxthinkcmf
chown -R www:www /data/uploads/rxthinkcmf

问题 2:上传后图片不显示 ​

原因: domain_url 配置错误或 Nginx 未配置静态文件处理。

解决:

  1. 检查 .env 中 DOMAIN_URL 是否正确
  2. 检查 Nginx 是否配置了 /uploads/ 的 alias
  3. 浏览器打开图片 URL 看是否能直接访问

问题 3:文件大小限制不生效 ​

原因: PHP 配置限制了上传大小。

解决:

ini
; php.ini
upload_max_filesize = 20M
post_max_size = 25M
max_execution_time = 300

问题 4:临时文件未清理 ​

原因: temp/ 目录中的文件在表单提交后未被 save_file() 迁移。

解决: 定期清理 temp/ 目录中超过 1 天的文件:

bash
# 定时任务:每天凌晨清理 1 天前的临时文件
find /data/uploads/rxthinkcmf/temp/ -type f -mtime +1 -delete

安全建议 ​

建议说明
上传目录放在项目外防止被 Web 直接访问源码
Nginx 禁止执行 PHP防止上传恶意 PHP 文件并执行
扩展名白名单只允许已知安全的文件类型
MIME 类型检查finfo 检测真实 MIME,防止伪造扩展名
随机文件名防止路径遍历和文件名注入
文件大小限制防止大文件 DoS 攻击
定期清理临时文件避免磁盘空间被占满

小蚂蚁云团队 · 提供技术支持