本文约 5,207 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:改了一个地方,还是传不上去
上传一个 30MB 的视频,WordPress 提示:
上传的文件已超过 php.ini 中 upload_max_filesize 指令
于是去改了 upload_max_filesize = 64M,重启,还是失败。再改 post_max_size,还是失败。最后发现是 Nginx 的 client_max_body_size 卡着。
上传体积的限制分布在四个独立的层,任何一层卡住都会失败,而 WordPress 的报错提示只提了 PHP 那一个——这就是让人反复返工的原因。
原理分析:上传请求要经过四道门
浏览器 POST 请求
↓
[1] CDN / WAF 层(Cloudflare 100MB、WAF 规则)
↓
[2] Web 服务器层(Nginx client_max_body_size / Apache LimitRequestBody)
↓
[3] PHP 层(upload_max_filesize、post_max_size、memory_limit、max_execution_time)
↓
[4] WordPress 应用层(多站点的 max_upload_size、插件自己的限制)
↓
写入磁盘 / 对象存储
每一层都有默认值,且默认都很小:
| 层 | 默认限制 |
|---|---|
| Cloudflare 免费版 | 100MB |
| Nginx | 1MB(client_max_body_size 默认) |
| PHP | 2MB(upload_max_filesize)、8MB(post_max_size) |
| WordPress 单站 | 由 PHP 决定 |
| WordPress 多站点 | 网络设置里单独限制,默认 1500KB |
| All-in-One WP Migration | 插件自己限制,免费版 512MB(需改) |
关键规则:post_max_size 必须 ≥ upload_max_filesize,否则表单还没到 PHP 就被拒了。
保姆级实操
第一层:CDN / WAF
Cloudflare 免费版单文件上传上限 100MB,付费版可提至 500MB。超过这个体积的请求会在 Cloudflare 层被拒(返回 413)。
如果用了阿里云/腾讯云 CDN,回源也有体积限制(通常默认 1GB,一般够用)。
WAF(安全狗、云锁、宝塔防火墙)也可能有 POST 体积限制,去面板里查。
第二层:Web 服务器
Nginx(最常被忽略的一层):
http {
client_max_body_size 64m;
}
# 或只针对某个站点
server {
client_max_body_size 64m;
}
宝塔面板:软件商店 → Nginx → 配置修改 → 在 http 块里加 client_max_body_size 64m;(或者:网站 → 设置 → 配置文件 → server 块里加)。
改完必须重载:
nginx -t && systemctl reload nginx
Apache:
# .htaccess 或虚拟主机配置
LimitRequestBody 67108864
php_value upload_max_filesize 64M
php_value post_max_size 64M
或者 httpd.conf:
<Directory "/var/www/site">
LimitRequestBody 67108864
</Directory>
第三层:PHP
找到 php.ini 的真实位置(很多人改错了文件):
php --ini
# 或
php -i | grep "Loaded Configuration"
WordPress 后台也能看:工具 → 站点健康 → 信息 → 服务器。
CLI 和 FPM 的 php.ini 通常是两个文件:
php --ini # CLI:/etc/php/8.2/cli/php.ini
# FPM:/etc/php/8.2/fpm/php.ini ← 这个才是 Web 用的
改 FPM 的那个:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
max_file_uploads = 20
重启 PHP-FPM:
sudo systemctl restart php8.2-fpm
宝塔:软件商店 → PHP-8.2 → 配置修改 / 上传限制。
验证:
php -r 'echo ini_get("upload_max_filesize"), " / ", ini_get("post_max_size"), "\n";'
注意 CLI 的值可能和 FPM 不同。更可靠的验证是建一个 phpinfo.php 通过浏览器访问(用完删掉),或者用 WordPress 的站点健康页。
第四层:WordPress 应用层
单站点:WordPress 读取 PHP 的值显示。可以在媒体上传页看到”最大上传文件大小”。
强制改大(某些虚拟主机不允许改 php.ini 时):
// wp-config.php
@ini_set( 'upload_max_size', '64M' );
@ini_set( 'post_max_size', '64M' );
@ini_set( 'memory_limit', '256M' );
注意:很多主机禁用了 ini_set 对这些指令的修改(PHP_INI_SYSTEM 级别只能在 php.ini 改)。这时只能找服务商。
多站点
网络管理 → 设置 → 网络设置 → 最下方”最大上传文件大小”和”站点默认上传空间”。
命令行:
wp network meta get 1 max_upload_size
wp network meta update 1 max_upload_size 67108864 # 单位字节
wp network meta update 1 blog_upload_space 1024 # 单位 MB
插件自己的限制
All-in-One WP Migration 免费版限制导入体积(其实底层是 PHP 限制),需要改:
// wp-config.php
// 注意:这个常量已在插件新版本移除,主要靠改 PHP 限制
更靠谱的做法:超过 PHP 限制的大文件不要用浏览器上传,直接用 WP-CLI 或 scp + 命令行导入(详见 大文件 WXR 分片导入)。
第五层:超时也要一起改
大文件上传慢,超时同样失败:
# Nginx
client_body_timeout 120s;
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
proxy_read_timeout 300;
; php.ini
max_execution_time = 300
max_input_time = 300
一次到位的配置清单(64MB 为例)
# 1. php.ini (FPM)
sudo sed -i 's/^upload_max_filesize.*/upload_max_filesize = 64M/' /etc/php/8.2/fpm/php.ini
sudo sed -i 's/^post_max_size.*/post_max_size = 64M/' /etc/php/8.2/fpm/php.ini
sudo sed -i 's/^memory_limit.*/memory_limit = 256M/' /etc/php/8.2/fpm/php.ini
sudo sed -i 's/^max_execution_time.*/max_execution_time = 300/' /etc/php/8.2/fpm/php.ini
# 2. Nginx
sudo sed -i 's/^http {/http {\n client_max_body_size 64m;/' /etc/nginx/nginx.conf
# 或手动加到 server 块
# 3. 重启
sudo systemctl restart php8.2-fpm
sudo nginx -t && sudo systemctl reload nginx
验证是否真的生效
wp eval 'echo "upload_max: ", ini_get("upload_max_filesize"), " | post_max: ", ini_get("post_max_size"), " | memory: ", ini_get("memory_limit"), "\n";'
前台验证:媒体库 → 添加 → 看页面下方显示的”最大上传文件大小”。
常见踩坑与失败案例
- 案例一:改了 CLI 的 php.ini(
php --ini显示的那个)但 Web 用的是 FPM 的,改了半天没效果。一定要改 FPM 的 php.ini。 - 案例二:PHP 改好了,Nginx 的
client_max_body_size还是 1m,上传 5MB 的文件返回 413 Request Entity Too Large。 - 改完没重启:改 php.ini 要重启 PHP-FPM,改 nginx.conf 要 reload nginx。宝塔面板改的话它会自动重启。
post_max_size小于upload_max_filesize:设成一样大或 post 更大。- 案例三:多站点网络设置里限制是 1500KB,PHP 改到 64M 也没用——子站上传仍被限制在 1.5MB。多站点必须改网络设置。
- Cloudflare 100MB 限制:上传 150MB 的文件,怎么改 PHP 都没用,会在 Cloudflare 层被拒(返回 413)。要么压缩文件,要么临时暂停 Cloudflare 代理(改 DNS 为 DNS only)再传。
memory_limit太小:大图处理(生成缩略图)会吃内存,上传成功但处理失败,媒体库里出现损坏的附件。- Windows IIS:要改
web.config的maxAllowedContentLength:
xml
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="67108864" />
</requestFiltering>
</security>
</system.webServer>
总结
上传体积受限时要逐层排查:CDN(Cloudflare 100MB)→ Web 服务器(Nginx client_max_body_size)→ PHP(upload_max_filesize ≤ post_max_size)→ WordPress(多站点网络设置 + 插件限制),超时参数(max_execution_time、fastcgi_read_timeout)也要一起改。四个高频坑:改了 CLI 的 php.ini 而不是 FPM 的、忘了改 Nginx、改完没重启服务、多站点忘了改网络设置。验证用站点健康页或媒体上传页显示的”最大上传文件大小”,比看 php.ini 可靠。超过 100MB 的文件建议不走浏览器上传,用 scp + WP-CLI 命令行处理。
