本文约 4,768 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:进度条卡住,然后是一句看不懂的英文
演示数据导入失败的表现形式很多:进度条停在某个百分比不动;弹一句 The response is not a valid JSON response;浏览器直接 500;或者导入显示成功,但媒体全是占位符。
它们背后的原因其实是有限的几类,而且有明确的排查顺序。难点在于错误信息往往指向错误的方向——比如 not a valid JSON response 看起来像是 AJAX 坏了,实际上九成情况是内存不足或进程超时导致 PHP 在中途被杀掉,返回了半截 HTML 错误页,前端解析 JSON 当然失败。
本文按“四条主线”来组织:内存上限、执行时间限制、REST/权限通路、以及缺失的必需插件。按这个顺序走,绝大多数导入问题都能在二十分钟内定位。如果你遇到的不是失败而是“导入了但不像演示站”,请转看为什么导入演示数据后和演示站不一样。
原理分析:导入流程到底经过哪些关卡
一次 Web 方式的演示导入(以 OCDI 为例)是这样的:
- 浏览器带着 selected demo index 发一次 AJAX/REST 请求
- 服务端下载或读取本地的 XML + JSON 配置文件
- 解析 XML(这一步最吃内存:整个 DOM 载入内存)
- 逐条
wp_insert_post/wp_insert_attachment写入数据库 - 处理附件下载(要发外部 HTTP 请求,受服务器的出站网络限制)
- 返回 JSON 结果给前端
任何一步超过 memory_limit 或 max_execution_time,PHP 就会被杀掉,返回的是错误页而不是 JSON——前端因此报 “not a valid JSON response”。这就是为什么这条错误信息几乎总是假的。
另外两处容易被忽略:第 5 步需要服务器能访问外网(很多国内服务器对外部 CDN 的连通性不稳定),以及 AJAX/REST 需要未被安全插件/防火墙拦截(Wordfence、Cloudflare 的 Bot Fight Mode 都可能拦下管理员自己的导入请求)。
保姆级实操
第一步:先把真实错误挖出来。
// wp-config.php —— 临时开启调试(排查结束后务必关掉)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
# 导入过程中实时盯日志
tail -f wp-content/debug.log
# 若没有该文件,看 PHP-FPM/Apache 的错误日志
tail -f /var/log/php-fpm/www-error.log 2>/dev/null
日志里若出现 Allowed memory size of X bytes exhausted,就是内存问题;出现 Maximum execution time of 30 seconds exceeded,就是超时。
第二步:抬高 PHP 限制。
// wp-config.php —— 放在 ABSPATH 定义之后
define( 'WP_MEMORY_LIMIT', '512M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
@ini_set( 'memory_limit', '512M' );
@set_time_limit( 300 );
注意:WP_MEMORY_LIMIT 只对 WordPress 上下文有效,WP_MAX_MEMORY_LIMIT 用于 admin 侧。若主机面板限制了 PHP 池的上限,还需要在 php.ini 或 PHP-FPM pool 配置里放开。
; php.ini / www.conf
memory_limit = 512M
max_execution_time = 300
upload_max_filesize = 64M
post_max_size = 64M
max_input_vars = 5000
Nginx 用户还要确认代理层的超时不小于 PHP 侧:
location ~ \.php$ {
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
client_max_body_size 64m;
}
第三步:确认必需插件已安装并激活。
这是被低估的一步。多数主题的 demo 内容包含构建器(Elementor/WPBakery/Gutenberg 自定义区块)的标记,缺插件时导入过程会在 wp_insert_post 后处理 meta 时出问题,或直接跳过内容。
wp plugin list --status=active --fields=name,version --format=table
grep -rn "tgmpa_register" wp-content/themes/当前主题/ -l | head -2
对照主题文档里的 Required Plugins 清单逐个核对。顺序很重要:先装齐插件,再导入。
第四步:绕开 Web 界面,用命令行导入。
这是最有效的一招——命令行不受 max_execution_time 的浏览器等待限制,也不受安全插件的 AJAX 拦截。
# 安装官方导入器
wp plugin install wordpress-importer --activate
# 导入 WXR(若主题的 demo 包里提供了 XML)
wp import wp-content/plugins/主题/languages/../demo/demo-content.xml --authors=create --skip=image-resize
很多商业主题把 demo XML 放在安装包(demo-content/ 或 sample-data/ 目录)里:
find wp-content/themes/当前主题 -name "*.xml" -o -name "*.wxr" | head
没有 XML 的主题通常依赖其自建导入器,这类情况就得修好 Web 通路。
第五步:修好 REST/AJAX 通路(针对 not a valid JSON response)。
# 1) 检查 REST 是否可达
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-json/wp/v2/posts
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-admin/admin-ajax.php
# 2) 检查是否被主题/htaccess 重定向
curl -sIL https://example.com/wp-json/wp/v2/ | grep -i "^HTTP\|^location"
# 3) 确认固定链接结构不是 "朴素"(朴素模式下 REST 常常异常)
wp option get permalink_structure
常见修复:把固定链接改为 /%postname%/,临时停用安全插件(Wordfence 的 Firewall、登录保护),以及关闭 CDN 的 Bot Fight Mode。Cloudflare 用户可临时对 wp-admin/admin-ajax.php 停用托管挑战规则。
第六步:附件下载失败的单独处理。
如果导入成功但图片全空:
# 1) 检查服务器出站连通性
curl -sI -o /dev/null -w "%{http_code}\n" https://demo.主题官网.com/wp-content/uploads/xxx.jpg
# 2) 若被防火墙拦截,改用手动方式:取出 Attachments XML,本地重新关联
wp media regenerate --yes --skip-delete
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='attachment' AND guid LIKE '%placeholder%';"
第七步:失败后先清干净再重试。
# 半途而废的导入会留下垃圾数据,重来之前清理
wp site empty --yes
wp transient delete --all
wp cache flush
# 导入前把所有内容重置(含媒体)
wp post delete $(wp post list --post_type=attachment --format=ids) --force
常见踩坑
- 看到
not a valid JSON response就去查 JSON。它几乎总是资源限制(内存/超时)造成的半截响应。 - 只改
wp-config.php不改 php.ini。很多主机的 PHP 池 Hard Limit 更低,WP_MEMORY_LIMIT无效。 - 改了 PHP 超时忘了改 Nginx/Apache。代理层 60 秒就断,前面改到 300 也白搭。
- 没装必需插件就导入。内容能进去但 meta/字段名对不上,表现为“导入了但页面是空的”。
- 开着 Wordfence/Cloudflare Bot Fight 模式。它们会把管理员自己的 AJAX 请求判定为机器人。
- 固定链接是“朴素”模式。REST 与 AJAX 在部分主机上会失效。
- 案例:某主机声称
memory_limit已是 512M,导入仍在第 30% 崩。日志显示Allowed memory size of 134217728 bytes exhausted(128M)——原因是 WordPress 的WP_MEMORY_LIMIT没设,实际取的是 PHP 池的值,而面板显示的是“另一个环境的配置”。最终在wp-config.php里显式定义WP_MEMORY_LIMIT为 512M 才通过。教训:不要相信主机的宣传参数,用wp eval "echo WP_MEMORY_LIMIT;"或 phpinfo 亲自验证。
总结
固定排查顺序(内容之外的菜单/首页/配色缺失,请对照为什么导入演示数据后和演示站不一样补齐):开 debug.log 拿真实报错 → 抬 memory_limit 与 max_execution_time(PHP + Nginx 双层)→ 装齐必需插件 → 改用 wp import 命令行绕开 Web → 校验 REST/admin-ajax 通路与固定链接 → 清理半途残留后重试。
三条判断经验:出现 JSON 报错先看日志而不是查代码;附件全空优先查出站网络;反复失败就用 CLI——绕开浏览器和 HTTP 层之后,绝大多数问题都会自然消失。最后记得排查完把 WP_DEBUG 关掉,别把调试日志留在生产环境。
