这是本文档旧的修订版!
DokuWiki 配置 URL 重写后媒体文件、Logo 和缩略图无法显示的排查记录
最近我在给自己的 DokuWiki 配置 URL 重写,也就是让原本类似:
/doku.php?id=start
这样的地址变成更简洁的:
/start
配置过程中,页面本身很快就能正常访问了,但随后遇到了一个比较隐蔽的问题:上传的媒体文件、网站 Logo 和部分缩略图无法正常显示。
这篇文章记录一下完整排查过程和最终解决方案。
一、环境说明
我的 DokuWiki 安装路径为:
/www/wwwroot/dokuwiki
媒体文件实际存放路径为:
/www/wwwroot/dokuwiki/data/media
网站使用:Nginx + PHP + DokuWiki + Cloudflare
DokuWiki 媒体文件并不是直接通过 /data/media/xxx.png 访问,而是通过 DokuWiki 的 PHP 程序处理,例如:
/_media/logo.png
最终会被重写到:
/lib/exe/fetch.php?media=logo.png
这点非常重要,不能为了让图片能访问就直接开放 /data/media 目录。
—
二、最初的 Nginx 重写规则
我最初添加了类似下面的规则:
location / { try_files $uri $uri/ @dokuwiki; } location @dokuwiki { rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last; rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last; rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last; rewrite ^/(.*) /doku.php?id=$1&$args last; }
页面访问没有问题,但媒体文件无法访问。
后来发现,问题出在 Nginx 的静态资源缓存规则上。
配置里还有这样的规则:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; error_log /dev/null; access_log /dev/null; }
而 DokuWiki 的媒体 URL 是这样的:
/_media/logo.png
因为它以 .png 结尾,所以请求会被上面的图片缓存规则提前匹配,Nginx 会尝试直接寻找:
/www/wwwroot/dokuwiki/_media/logo.png
但实际文件并不在这个位置,而是在:
/www/wwwroot/dokuwiki/data/media/logo.png
因此返回 404。
三、修复媒体文件无法访问
解决方法是:给 /_media/、/_detail/、/_export/ 单独写高优先级 location,并放在静态资源缓存规则之前。
最终使用的规则如下:
location ^~ /_media/ { rewrite ^/_media/(.*)$ /lib/exe/fetch.php?media=$1 last; } location ^~ /_detail/ { rewrite ^/_detail/(.*)$ /lib/exe/detail.php?media=$1 last; } location ^~ /_export/ { rewrite ^/_export/([^/]+)/(.*)$ /doku.php?do=export_$1&id=$2 last; } location / { try_files $uri $uri/ @dokuwiki; } location @dokuwiki { rewrite ^/(.*) /doku.php?id=$1&$args last; }
这里使用了:
^~
表示只要匹配到这个前缀,就不再继续匹配后面的正则 location。
这样 /_media/logo.png 就不会被图片缓存规则截走,而是会正确交给 DokuWiki 的 fetch.php 处理。
四、不要直接开放 data 目录
DokuWiki 的 data、conf、inc、vendor 等目录不应该被外部直接访问。
可以保留这样的安全规则:
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md|data|conf|bin|inc|vendor) { return 404; }
这样可以防止访问:
/data/media/logo.png /conf/local.php /inc/
媒体文件应通过:
/_media/logo.png
由 DokuWiki 控制输出。
五、Logo 和缩略图仍然无法显示
媒体文件可以直接打开后,我又遇到了第二个问题。
页面中的 Logo 和缩略图仍然无法显示,例如:
<img id="dw__logo" src="/_media/logo.png">
以及:
<img src="/_media/capture_2025-11-11_185838.png?w=90&h=90&tok=68fe3f">
但奇怪的是,某些带参数的图片又可以访问:
/_media/logo.png?t=1706014361&w=64&h=64&tok=e2dbf1
为了进一步判断问题,我在终端使用 `curl -I` 测试了几个地址:
curl -I "https://www.example.com/_media/logo.png" curl -I "https://www.example.com/_media/logo.png?t=1706014361&w=64&h=64&tok=e2dbf1" curl -I "https://www.example.com/lib/exe/fetch.php?media=logo.png" curl -I "https://www.example.com/lib/exe/fetch.php?media=logo.png&t=1706014361&w=64&h=64&tok=e2dbf1"
结果发现:
/_media/logo.png
返回:
HTTP/2 404 cf-cache-status: HIT
而:
/lib/exe/fetch.php?media=logo.png
返回:
HTTP/2 200 content-type: image/png
这说明源站和 DokuWiki 本身已经正常,真正的问题是:Cloudflare 缓存了之前的 404 页面。
六、最终解决:清理 Cloudflare 缓存
进入 Cloudflare 后台:
缓存 → 配置 → 清除所有内容
清理后再次测试:
curl -I "https://www.example.com/_media/logo.png"
返回变成:
HTTP/2 200 content-type: image/png
此时 Logo 和缩略图也恢复正常。
七、最终推荐配置片段
下面是最终比较稳定的 DokuWiki Nginx 伪静态配置片段:
# 禁止访问敏感文件和目录 location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md|data|conf|bin|inc|vendor) { return 404; } # SSL 证书验证目录 location ^~ /.well-known/ { allow all; } # DokuWiki 媒体文件 location ^~ /_media/ { rewrite ^/_media/(.*)$ /lib/exe/fetch.php?media=$1 last; } location ^~ /_detail/ { rewrite ^/_detail/(.*)$ /lib/exe/detail.php?media=$1 last; } location ^~ /_export/ { rewrite ^/_export/([^/]+)/(.*)$ /doku.php?do=export_$1&id=$2 last; } # DokuWiki 页面 URL 重写 location / { try_files $uri $uri/ @dokuwiki; } location @dokuwiki { rewrite ^/(.*) /doku.php?id=$1&$args last; } # 静态图片缓存 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 重写。
进入:管理 → 配置设置 → 高级设置
设置:
使用更整洁的URLuserewrite 为.htaccess
启用在 URL 中使用斜杠作为命名空间的分隔符useslash
九、排查经验总结
这次问题主要分为三个阶段:
第一,页面 URL 重写正常,但媒体文件 404。
原因是 /_media/*.png 被 Nginx 的图片缓存 location 提前匹配,导致 Nginx 直接去文件系统寻找 /_media/ 目录。
解决方法是给 /_media/ 单独写:
location ^~ /_media/
并放在图片缓存规则之前。
第二,媒体文件直接访问恢复,但 Logo 和缩略图仍然异常。
这时需要用 curl -I 分别测试:
/_media/logo.png /lib/exe/fetch.php?media=logo.png
如果 fetch.php 能返回 200,说明 DokuWiki 正常,问题不在 PHP 层。
第三,发现 Cloudflare 返回的是旧的 404 缓存。
判断依据是响应头里出现:
cf-cache-status: HIT age: xxxx HTTP/2 404
说明请求甚至没有回到源站,而是 Cloudflare 直接返回了缓存结果。
最终清理 Cloudflare 缓存后,问题全部解决。
十、结论
DokuWiki 配置 URL 重写时,媒体文件无法显示并不一定是 DokuWiki 本身的问题,常见原因有:
Nginx location 匹配顺序错误 静态资源缓存规则截走了 /_media/ 请求 Cloudflare 缓存了旧的 404 DokuWiki 页面缓存或缩略图缓存未刷新
排查时不要只看浏览器页面显示效果,最好用:curl -I
分别检查:
/_media/xxx.png /lib/exe/fetch.php?media=xxx.png
这样可以快速判断问题到底出在:
Nginx 重写 DokuWiki PHP 处理 Cloudflare 缓存 浏览器缓存
这次最终的关键点在于
- Nginx 使用 ^~ /_media/ 防止媒体请求被静态图片规则截走
- Cloudflare 清理旧的 404 缓存
完成这两步后,DokuWiki 的 URL 重写、媒体文件、Logo 和缩略图都恢复正常。
评论