Files
easygoadmin-wiki/EasyGoAdmin_Beego_EleVue/zh/tools/upload-config.md
T
2026-10-20 21:19:44 +08:00

336 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 7.2 上传配置详解
:::tip 概述
文件上传配置定义在 `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_EXT` | `gif,jpg,jpeg,png,bmp,webp,svg` | 图片允许后缀 |
| `file_ext` | `[FILE] FILE_EXT` | 多种后缀 | 文件允许后缀 |
| `max_size` | `[FILE] MAX_SIZE` | `10` | 单文件最大大小(MB) |
### upload_dir — 上传根目录
```ini
; .env
[FILE]
UPLOAD_DIR = D:\xampp8.2\htdocs\RXThinkCMF_ThinkPhp8_EleVue\uploads
```
**要求:**
- 必须是绝对路径
- 目录必须存在且有写入权限
- 生产环境建议放在项目目录外(防止被 Web 直接访问)
**各环境示例:**
| 环境 | 路径示例 |
|------|---------|
| Windows 开发 | `D:\xampp8.2\htdocs\RXThinkCMF_ThinkPhp8_EleVue\uploads` |
| Linux 开发 | `/home/www/uploads` |
| Linux 生产 | `/opt/data/uploads` |
| Docker | `/data/apps/uploads`(挂载卷) |
### domain_url — 文件访问域名
```ini
; .env
[FILE]
DOMAIN_URL = https://cdn.example.com
```
**要求:**
- 不要以 `/` 结尾
- 必须是前端可访问的域名
- 本地开发可留空(使用相对路径)
**各环境示例:**
| 环境 | 域名示例 |
|------|---------|
| 本地开发 | (留空,使用相对路径) |
| 测试环境 | `http://file.thinkphp8.elevue` |
| 生产环境 | `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 MB | PDF/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:\xampp8.2\htdocs\RXThinkCMF_ThinkPhp8_EleVue\uploads
DOMAIN_URL =
MAX_SIZE = 10
```
### 测试环境
```ini
[FILE]
UPLOAD_DIR = /home/www/uploads
DOMAIN_URL = http://file.thinkphp8.elevue
MAX_SIZE = 10
```
### 生产环境
```ini
[FILE]
UPLOAD_DIR = /opt/data/uploads
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 = /opt/data/uploads
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 = /opt/data/uploads
fileSaveDir = article
结果:
临时文件: /opt/data/uploads/temp/20260920/abc.jpg
正式文件: /opt/data/uploads/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 /opt/data/uploads/;
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 /opt/data/uploads
chown -R www:www /opt/data/uploads
```
### 问题 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 /opt/data/uploads/temp/ -type f -mtime +1 -delete
```
## 安全建议
| 建议 | 说明 |
|------|------|
| 上传目录放在项目外 | 防止被 Web 直接访问源码 |
| Nginx 禁止执行 PHP | 防止上传恶意 PHP 文件并执行 |
| 扩展名白名单 | 只允许已知安全的文件类型 |
| MIME 类型检查 | `finfo` 检测真实 MIME,防止伪造扩展名 |
| 随机文件名 | 防止路径遍历和文件名注入 |
| 文件大小限制 | 防止大文件 DoS 攻击 |
| 定期清理临时文件 | 避免磁盘空间被占满 |