网站迁移后图片和附件丢失,成因基本只有两类:文件没搬全,或者数据库里还留着旧域名、旧绝对路径。修复顺序固定为三步——先核对文件是否完整,再批量替换数据库里的 URL,最后扫 404 查漏补缺。按这个顺序做,WordPress 站点通常 30 分钟内修完,不需要一张张手动重传。
图片是真丢了,还是路径错了?先花 2 分钟判断
结论:直接请求图片的真实 URL,再对照页面源码,就能在 2 分钟内分清是「文件缺失」还是「路径/域名错」,两者的修法完全不同。
第一步,用 curl 直接敲静态文件地址:
curl -I https://新域名.com/wp-content/uploads/2024/01/cover.jpg
返回 200 说明文件在、路径对,问题出在页面输出的地址上;返回 404 且你用 ls 能在服务器上找到这个文件,说明是 Web 根目录、伪静态或权限问题;服务器上根本找不到这个文件,才是真的没搬过来。
第二步,打开出问题的页面看源码,搜 uploads,如果 src 里还是 https://旧域名.com/...,那属于数据库没替换,跟文件本身无关。
第一步:把文件搬全,别只验证首页
结论:迁移丢附件最常见的原因是只同步了整站目录、漏掉了单独挂载的上传目录,或者漏掉了隐藏文件和大小写不一致的文件。
推荐用 rsync 而不是 FTP 拖拽,支持断点续传和增量同步:
rsync -avz --progress /var/www/old/wp-content/uploads/ root@新服务器:/var/www/new/wp-content/uploads/
搬完必须比对两端,不能只看首页能不能打开:
find /var/www/new/wp-content/uploads -type f | wc -l
du -sh /var/www/new/wp-content/uploads
四个高频漏点记一下:一是 .htaccess、.user.ini 这类以点开头的隐藏文件;二是附件目录被单独挂到数据盘或对象存储(OSS/S3)上,迁移时忘了同步 bucket;三是 Windows 转 Linux 后文件名大小写敏感,Logo.JPG 和 logo.jpg 是两个文件;四是中文文件名从 GBK 转 UTF-8 后编码错乱,导致 404。
目录权限统一设成目录 755、文件 644:
find /var/www/new -type d -exec chmod 755 {} \;
find /var/www/new -type f -exec chmod 644 {} \;
第二步:批量替换数据库里的旧域名
结论:换域名迁移必须做一次全库 URL 替换,但绝对不能用裸 SQL 的 REPLACE() 直接改 WordPress 的核心表,会破坏序列化字段的长度前缀。
先备份,这一步不能省:
mysqldump -u root -p 数据库名 > backup_$(date +%F).sql
WordPress 站点用 WP-CLI 最稳,先空跑看影响行数,确认无误再执行:
wp search-replace 'https://旧域名.com' 'https://新域名.com' --all-tables --precise --recurse-objects --skip-columns=guid --dry-run
wp search-replace 'https://旧域名.com' 'https://新域名.com' --all-tables --precise --recurse-objects --skip-columns=guid
--precise 的作用就是正确处理 PHP 序列化数据,--skip-columns=guid 避免改动文章 GUID(GUID 是全局唯一标识,改它会导致订阅源重复推送)。非 WordPress 站点可以导出 SQL 后用编辑器批量替换,但同样要检查字段里有没有序列化内容。
替换完成后刷新 CDN 缓存,否则浏览器拿到的还是旧的 HTML。
第三步:扫 404 查漏,并防止下次复发
结论:批量替换后一定还会有零星漏网图片,用访问日志按后缀过滤,比人工翻页面快得多。
grep ' 404 ' /var/log/nginx/access.log | grep -Ei '\.(jpg|jpeg|png|gif|webp|pdf|zip|docx)$' | awk '{print $7}' | sort | uniq -c | sort -rn | head -50
输出的 Top 50 就是待修清单,逐条确认是补文件还是补重定向。旧域名不要立刻停解析,保留 301 跳转至少 3 个月:
server {
listen 443 ssl;
server_name 旧域名.com;
return 301 https://新域名.com$request_uri;
}
防复发的关键动作只有一个:把站内所有绝对地址改成相对地址或协议相对地址,下次再迁移就不会重演。另外迁移后记得强制 HTTPS,否则 http 与 https 混用会触发混合内容拦截,图片在浏览器里显示为「裂图」,看着像丢了其实是被拦了。
修不动的时候去哪问
社区的技术交流版块下设有「站长交流」和「运维」子分类,专治这类迁移遗留问题。发帖时把三样东西贴全——服务器上的 find 结果、curl -I 的返回头、后台的报错截图,基本一轮就能定位。提醒一句:站点有 30 秒发帖冷却,且未上传头像的账号不能发帖,先传头像再提问,能省一轮等待。
回到主线:迁移丢图从来不是「一张张补」的活,而是「文件完整性核对 + 数据库批量替换 + 日志扫漏」三件事按顺序做完。把这三步固化成迁移检查清单,第二次迁移就不会再踩同一个坑。