署名:DEVDIY
原文/延伸阅读:https://devdiy.cn/wordpress/
典型现象:后台「媒体 → 添加」选图后进度条跑完,提示「HTTP 错误」;或者「无法创建目录」「上传目录不可写」;有时小图能传、大图失败,有时只有某个月份目录失败。
多数不是「WordPress 坏了」,而是 PHP 上传限制、wp-content/uploads 权限、磁盘配额,或 open_basedir/upload_tmp_dir 把临时文件拦在外面。下面按「先看浏览器/服务器错误 → 再查 PHP 限制 → 再查目录与 SELinux → 最后排插件」走。
0. 先把真实错误拿出来
浏览器里只显示「HTTP 错误」往往不够。打开开发者工具(F12)→ Network,重新上传一次,点 async-upload.php(或 admin-ajax.php)那条请求:
- Status 是 413 → 反向代理 / Nginx client_max_body_size 太小;
- Status 是 500 → 看 PHP / Web 服务器错误日志;
- Status 是 200,但响应体是 HTML 或 {“success”:false,…} → 看返回 JSON 里的 data.message。
服务器日志优先看:
# PHP-FPM 常见路径(按发行版调整)
tail -n 100 /var/log/php*-fpm.log
# 或 Nginx / Apache 错误日志
tail -n 100 /var/log/nginx/error.log
tail -n 100 /var/log/apache2/error.log
日志里出现 Allowed memory size、POST Content-Length exceeds、Failed to open stream、Permission denied,就能直接定位,不必盲目改权限。
1. 核对 PHP 上传与内存限制
在站点根放一个临时 phpinfo 页(查完立刻删),或在 WP 后台装只读信息类插件,确认这三项:
| 配置项 | 建议起步值 | 说明 |
|---|---|---|
| upload_max_filesize | ≥ 32M | 单文件上限 |
| post_max_size | ≥ upload_max_filesize | 整次 POST 上限,必须 ≥ 上传限制 |
| memory_limit | ≥ 256M | 图片缩放、生成缩略图时更吃内存 |
| max_execution_time | ≥ 60 | 大图或慢磁盘时避免超时 |
改配置位置因环境而异:
- 宝塔 / 面板:软件商店 → PHP → 配置修改 / 上传限制;
- 自建 PHP-FPM:改 php.ini 后 systemctl reload php-fpm;
- 仅当前站点可用时,可在站点根 .user.ini(部分面板)写:
upload_max_filesize = 32M
post_max_size = 40M
memory_limit = 256M
改完后重新打开 phpinfo 确认生效。只改了 upload_max_filesize、没改 post_max_size,大图仍会失败。
WordPress 侧还可在 wp-config.php(That’s all, stop editing! 之前)加:
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');
这只影响 WP 申请的内存上限,不能突破 PHP 的 memory_limit,两者都要够。
2. 检查 uploads 目录是否可写、是否按月生成
标准路径:wp-content/uploads/。WordPress 默认按 年/月 建子目录。
在服务器上(路径按实际站点根调整):
cd /var/www/html/wp-content
ls -ld uploads
ls -ld uploads/$(date +%Y) uploads/$(date +%Y)/$(date +%m) 2>/dev/null
# PHP-FPM 用户常见为 www-data / nginx / www
namei -l uploads
经验值:
- 目录属主应是跑 PHP 的那个用户(如 www-data);
- 目录权限常见 755,文件 644;不要一上来就 777;
- 若当月目录不存在且父目录不可写,后台就会报「无法创建目录」。
修复示例(用户名按环境改):
chown -R www-data:www-data /var/www/html/wp-content/uploads
find /var/www/html/wp-content/uploads -type d -exec chmod 755 {} \;
find /var/www/html/wp-content/uploads -type f -exec chmod 644 {} \;
磁盘与 inode 也要看一眼:
df -h /var/www/html
df -i /var/www/html
Use% 到 100% 或 inode 耗尽时,上传会表现为随机 HTTP 错误。
3. open_basedir、upload_tmp_dir 与 SELinux
部分主机把 PHP 限制在站点目录内。若 upload_tmp_dir 指向 /tmp,而 open_basedir 不含 /tmp,上传临时文件会写失败。
在 phpinfo 里查:
- open_basedir
- upload_tmp_dir
- sys_temp_dir
处理思路:
- 把 upload_tmp_dir 改到站点内可写目录,例如 /var/www/html/wp-content/tmp,并确保该目录存在且属主正确;或
- 在 open_basedir 中追加系统临时目录(按主机商文档操作,勿随意放开整盘)。
CentOS / RHEL 上若开启 SELinux,还可能出现「权限看着对、仍 Permission denied」:
getenforce
# 临时验证(确认后再做持久化上下文,勿长期停 SELinux)
ausearch -m avc -ts recent | grep uploads
把上下文设回 httpd_sys_rw_content_t(具体命令以发行版文档为准)后再测上传。
4. Nginx / 反向代理的 body 大小
Nginx 默认 client_max_body_size 往往是 1m。超过就会 413,浏览器端可能仍显示成笼统的上传失败。
在对应 server 或 http 块:
client_max_body_size 40m;
重载:
nginx -t && systemctl reload nginx
前面若还有 CDN / 负载均衡,同样要查它们的请求体上限。
5. 排除插件与图片处理冲突
若「关掉所有插件、换默认主题」后就能上传:
- 逐个启用,定位安全类、图片压缩、对象存储(OSS/S3)插件;
- 对象存储插件若配错 Bucket / 密钥,常在本地写入成功后的「远程同步」阶段失败,表现仍像上传失败;
- 用 WP_DEBUG_LOG 抓堆栈:
// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
日志一般在 wp-content/debug.log。复现一次上传后查看最新几行,查完将 WP_DEBUG 改回 false。
6. 验证清单(做完打勾)
- Network 里 async-upload.php 不再是 413/500;
- phpinfo 中 upload_max_filesize ≤ post_max_size,且大于你要传的文件;
- uploads/年/月 存在且 PHP 用户可写;
- 磁盘与 inode 未满;
- 默认主题 + 停用插件后,同一张图能进媒体库并生成缩略图。
缩略图:上传成功后,在 uploads/年/月/ 下应能看到带 -150x150、-300x300 等后缀的衍生文件。只有原图、没有衍生文件时,再回头查 memory_limit 与 GD/Imagick 扩展是否启用。
本文由 DEVDIY 整理。我们日常更多时间花在 WordPress / Shopify 外贸站与微信小程序的开发和线上排查上,把这类「看起来像玄学、其实能逐步复现」的问题写成可执行步骤。
原文/延伸阅读:https://devdiy.cn/wordpress/
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/lgm252008/article/details/168859062




