显示页面过去修订反向链接全部折叠/展开回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== 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 重写规则 ===== 我最初添加了类似下面的规则: <code 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; } </code> 页面访问没有问题,但媒体文件无法访问。 后来发现,问题出在 Nginx 的静态资源缓存规则上。 配置里还有这样的规则: <code nginx> location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; error_log /dev/null; access_log /dev/null; } </code> 而 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,并放在静态资源缓存规则之前。** 最终使用的规则如下: <code nginx> 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; } </code> 这里使用了: <code nginx> ^~ </code> 表示只要匹配到这个前缀,就不再继续匹配后面的正则 location。 这样 ''/_media/logo.png'' 就不会被图片缓存规则截走,而是会正确交给 DokuWiki 的 ''fetch.php'' 处理。 ---- ===== 四、不要直接开放 data 目录 ===== DokuWiki 的 ''data''、''conf''、''inc''、''vendor'' 等目录不应该被外部直接访问。 可以保留这样的安全规则: <code nginx> location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md|data|conf|bin|inc|vendor) { return 404; } </code> 这样可以防止访问: /data/media/logo.png /conf/local.php /inc/ 媒体文件应通过: /_media/logo.png 由 DokuWiki 控制输出。 ---- ===== 五、Logo 和缩略图仍然无法显示 ===== 媒体文件可以直接打开后,我又遇到了第二个问题。 页面中的 Logo 和缩略图仍然无法显示,例如: <code html> <img id="dw__logo" src="/_media/logo.png"> </code> 以及: <code html> <img src="/_media/capture_2025-11-11_185838.png?w=90&h=90&tok=68fe3f"> </code> 但奇怪的是,某些带参数的图片又可以访问: /_media/logo.png?t=1706014361&w=64&h=64&tok=e2dbf1 为了进一步判断问题,我在终端使用 `curl -I` 测试了几个地址: <code bash> 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" </code> 结果发现: /_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 后台: 缓存 → 配置 → 清除所有内容 清理后再次测试: <code bash> curl -I "https://www.example.com/_media/logo.png" </code> 返回变成: HTTP/2 200 content-type: image/png 此时 Logo 和缩略图也恢复正常。 ---- ===== 七、最终推荐配置片段 ===== 下面是最终比较稳定的 DokuWiki Nginx 伪静态配置片段: <code 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; } </code> 修改完成后检查配置并重载 Nginx: ---- ===== 八、DokuWiki 后台配置 ===== DokuWiki 后台还需要开启 URL 重写。 进入:管理 → 配置设置 → 高级设置 设置: 使用更整洁的URL''userewrite'' 为''.htaccess'' 启用在 URL 中使用斜杠作为命名空间的分隔符''useslash'' ---- ===== 九、排查经验总结 ===== 这次问题主要分为三个阶段: 第一,页面 URL 重写正常,但媒体文件 404。 原因是 ''/_media/*.png'' 被 Nginx 的图片缓存 location 提前匹配,导致 Nginx 直接去文件系统寻找 ''/_media/'' 目录。 解决方法是给 ''/_media/'' 单独写: <code nginx> location ^~ /_media/ </code> 并放在图片缓存规则之前。 第二,媒体文件直接访问恢复,但 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 和缩略图都恢复正常。 {{tag>原创 dokuwiki}} blog/url重写.txt 最后更改: 2026/05/22 19:23由 doge24190