差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
| blog:url重写 [2026/05/22 17:38] – 移除 - 外部编辑 (未知日期) 127.0.0.1 | blog:url重写 [2026/05/22 19:23] (当前版本) – [一、环境说明] doge24190 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== DokuWiki 配置 URL 重写后媒体文件、Logo 和缩略图无法显示的排查记录 ====== | ||
| + | 最近我在给自己的 DokuWiki 配置 URL 重写,也就是让原本类似: | ||
| + | |||
| + | / | ||
| + | |||
| + | 这样的地址变成更简洁的: | ||
| + | |||
| + | /start | ||
| + | |||
| + | 配置过程中,页面本身很快就能正常访问了,但随后遇到了一个比较隐蔽的问题:**上传的媒体文件、网站 Logo 和部分缩略图无法正常显示**。 | ||
| + | |||
| + | 这篇文章记录一下完整排查过程和最终解决方案。 | ||
| + | |||
| + | |||
| + | ---- | ||
| + | |||
| + | |||
| + | ===== 一、环境说明 ===== | ||
| + | |||
| + | |||
| + | 我的 DokuWiki 安装路径为: | ||
| + | |||
| + | / | ||
| + | |||
| + | |||
| + | 媒体文件实际存放路径为: | ||
| + | |||
| + | / | ||
| + | |||
| + | |||
| + | 网站使用:Nginx + PHP + DokuWiki + Cloudflare | ||
| + | |||
| + | DokuWiki 媒体文件并不是直接通过 ''/ | ||
| + | |||
| + | / | ||
| + | |||
| + | 最终会被重写到: | ||
| + | |||
| + | / | ||
| + | |||
| + | 这点非常重要,不能为了让图片能访问就直接开放 ''/ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 二、最初的 Nginx 重写规则 ===== | ||
| + | |||
| + | |||
| + | 我最初添加了类似下面的规则: | ||
| + | |||
| + | <code nginx> | ||
| + | location / { | ||
| + | try_files $uri $uri/ @dokuwiki; | ||
| + | } | ||
| + | |||
| + | location @dokuwiki { | ||
| + | rewrite ^/ | ||
| + | rewrite ^/ | ||
| + | rewrite ^/ | ||
| + | rewrite ^/(.*) / | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 页面访问没有问题,但媒体文件无法访问。 | ||
| + | |||
| + | 后来发现,问题出在 Nginx 的静态资源缓存规则上。 | ||
| + | |||
| + | 配置里还有这样的规则: | ||
| + | |||
| + | <code nginx> | ||
| + | location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ | ||
| + | { | ||
| + | expires 30d; | ||
| + | error_log /dev/null; | ||
| + | access_log /dev/null; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 而 DokuWiki 的媒体 URL 是这样的: | ||
| + | |||
| + | / | ||
| + | |||
| + | 因为它以 '' | ||
| + | |||
| + | / | ||
| + | |||
| + | 但实际文件并不在这个位置,而是在: | ||
| + | |||
| + | / | ||
| + | |||
| + | 因此返回 404。 | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 三、修复媒体文件无法访问 ===== | ||
| + | |||
| + | 解决方法是:**给 ''/ | ||
| + | |||
| + | 最终使用的规则如下: | ||
| + | |||
| + | <code nginx> | ||
| + | location ^~ /_media/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | location ^~ /_detail/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | location ^~ /_export/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | location / { | ||
| + | try_files $uri $uri/ @dokuwiki; | ||
| + | } | ||
| + | |||
| + | location @dokuwiki { | ||
| + | rewrite ^/(.*) / | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 这里使用了: | ||
| + | |||
| + | <code nginx> | ||
| + | ^~ | ||
| + | </ | ||
| + | |||
| + | 表示只要匹配到这个前缀,就不再继续匹配后面的正则 location。 | ||
| + | |||
| + | 这样 ''/ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 四、不要直接开放 data 目录 ===== | ||
| + | |||
| + | DokuWiki 的 '' | ||
| + | |||
| + | 可以保留这样的安全规则: | ||
| + | |||
| + | <code nginx> | ||
| + | location ~ ^/ | ||
| + | { | ||
| + | return 404; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 这样可以防止访问: | ||
| + | |||
| + | / | ||
| + | / | ||
| + | /inc/ | ||
| + | |||
| + | 媒体文件应通过: | ||
| + | |||
| + | / | ||
| + | |||
| + | 由 DokuWiki 控制输出。 | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 五、Logo 和缩略图仍然无法显示 ===== | ||
| + | |||
| + | |||
| + | 媒体文件可以直接打开后,我又遇到了第二个问题。 | ||
| + | |||
| + | 页面中的 Logo 和缩略图仍然无法显示,例如: | ||
| + | |||
| + | <code html> | ||
| + | <img id=" | ||
| + | </ | ||
| + | |||
| + | 以及: | ||
| + | |||
| + | <code html> | ||
| + | <img src="/ | ||
| + | </ | ||
| + | |||
| + | 但奇怪的是,某些带参数的图片又可以访问: | ||
| + | |||
| + | / | ||
| + | |||
| + | 为了进一步判断问题,我在终端使用 `curl -I` 测试了几个地址: | ||
| + | |||
| + | <code bash> | ||
| + | curl -I " | ||
| + | curl -I " | ||
| + | curl -I " | ||
| + | curl -I " | ||
| + | </ | ||
| + | |||
| + | 结果发现: | ||
| + | |||
| + | / | ||
| + | |||
| + | 返回: | ||
| + | |||
| + | HTTP/2 404 | ||
| + | cf-cache-status: | ||
| + | |||
| + | 而: | ||
| + | |||
| + | / | ||
| + | |||
| + | 返回: | ||
| + | |||
| + | HTTP/2 200 | ||
| + | content-type: | ||
| + | |||
| + | 这说明源站和 DokuWiki 本身已经正常,真正的问题是:**Cloudflare 缓存了之前的 404 页面。** | ||
| + | |||
| + | ===== 六、最终解决:清理 Cloudflare 缓存 ===== | ||
| + | |||
| + | 进入 Cloudflare 后台: | ||
| + | |||
| + | 缓存 → 配置 → 清除所有内容 | ||
| + | |||
| + | |||
| + | 清理后再次测试: | ||
| + | |||
| + | <code bash> | ||
| + | curl -I " | ||
| + | </ | ||
| + | |||
| + | 返回变成: | ||
| + | |||
| + | HTTP/2 200 | ||
| + | content-type: | ||
| + | |||
| + | 此时 Logo 和缩略图也恢复正常。 | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 七、最终推荐配置片段 ===== | ||
| + | |||
| + | 下面是最终比较稳定的 DokuWiki Nginx 伪静态配置片段: | ||
| + | |||
| + | <code nginx> | ||
| + | # 禁止访问敏感文件和目录 | ||
| + | location ~ ^/ | ||
| + | { | ||
| + | return 404; | ||
| + | } | ||
| + | |||
| + | # SSL 证书验证目录 | ||
| + | location ^~ / | ||
| + | allow all; | ||
| + | } | ||
| + | |||
| + | # DokuWiki 媒体文件 | ||
| + | location ^~ /_media/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | location ^~ /_detail/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | location ^~ /_export/ { | ||
| + | rewrite ^/ | ||
| + | } | ||
| + | |||
| + | # DokuWiki 页面 URL 重写 | ||
| + | location / { | ||
| + | try_files $uri $uri/ @dokuwiki; | ||
| + | } | ||
| + | |||
| + | location @dokuwiki { | ||
| + | rewrite ^/(.*) / | ||
| + | } | ||
| + | |||
| + | # 静态图片缓存 | ||
| + | location ~* \.(gif|jpg|jpeg|png|bmp|swf|webp|svg|ico)$ | ||
| + | { | ||
| + | expires 30d; | ||
| + | error_log /dev/null; | ||
| + | access_log off; | ||
| + | } | ||
| + | |||
| + | # JS/CSS 缓存 | ||
| + | location ~* \.(js|css)$ | ||
| + | { | ||
| + | expires 12h; | ||
| + | error_log /dev/null; | ||
| + | access_log off; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 修改完成后检查配置并重载 Nginx: | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 八、DokuWiki 后台配置 ===== | ||
| + | |||
| + | DokuWiki 后台还需要开启 URL 重写。 | ||
| + | |||
| + | 进入:管理 → 配置设置 → 高级设置 | ||
| + | |||
| + | 设置: | ||
| + | |||
| + | 使用更整洁的URL'' | ||
| + | 启用在 URL 中使用斜杠作为命名空间的分隔符'' | ||
| + | ---- | ||
| + | |||
| + | ===== 九、排查经验总结 ===== | ||
| + | |||
| + | 这次问题主要分为三个阶段: | ||
| + | |||
| + | 第一,页面 URL 重写正常,但媒体文件 404。 | ||
| + | |||
| + | 原因是 ''/ | ||
| + | |||
| + | 解决方法是给 ''/ | ||
| + | |||
| + | <code nginx> | ||
| + | location ^~ /_media/ | ||
| + | </ | ||
| + | |||
| + | 并放在图片缓存规则之前。 | ||
| + | |||
| + | 第二,媒体文件直接访问恢复,但 Logo 和缩略图仍然异常。 | ||
| + | |||
| + | 这时需要用 '' | ||
| + | |||
| + | / | ||
| + | / | ||
| + | |||
| + | 如果 '' | ||
| + | |||
| + | 第三,发现 Cloudflare 返回的是旧的 404 缓存。 | ||
| + | |||
| + | 判断依据是响应头里出现: | ||
| + | |||
| + | cf-cache-status: | ||
| + | age: xxxx | ||
| + | HTTP/2 404 | ||
| + | |||
| + | 说明请求甚至没有回到源站,而是 Cloudflare 直接返回了缓存结果。 | ||
| + | |||
| + | 最终清理 Cloudflare 缓存后,问题全部解决。 | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 十、结论 ===== | ||
| + | |||
| + | DokuWiki 配置 URL 重写时,媒体文件无法显示并不一定是 DokuWiki 本身的问题,常见原因有: | ||
| + | |||
| + | Nginx location 匹配顺序错误 | ||
| + | 静态资源缓存规则截走了 /_media/ 请求 | ||
| + | Cloudflare 缓存了旧的 404 | ||
| + | DokuWiki 页面缓存或缩略图缓存未刷新 | ||
| + | |||
| + | 排查时不要只看浏览器页面显示效果,最好用:'' | ||
| + | |||
| + | 分别检查: | ||
| + | |||
| + | / | ||
| + | / | ||
| + | |||
| + | 这样可以快速判断问题到底出在: | ||
| + | |||
| + | Nginx 重写 | ||
| + | DokuWiki PHP 处理 | ||
| + | Cloudflare 缓存 | ||
| + | 浏览器缓存 | ||
| + | |||
| + | 这次最终的关键点在于 | ||
| + | |||
| + | - Nginx 使用 ^~ /_media/ 防止媒体请求被静态图片规则截走 | ||
| + | - Cloudflare 清理旧的 404 缓存 | ||
| + | |||
| + | 完成这两步后,DokuWiki 的 URL 重写、媒体文件、Logo 和缩略图都恢复正常。 | ||
| + | |||
| + | {{tag> | ||