Webman静态文件404主因是public_path()路径错误、config/static.php中enable为false、StaticFile中间件未启用、中文路径未urldecode,或Nginx与Webman静态职责混淆。

Webman 静态文件访问失败,90% 不是代码写错了,而是 public_path() 指向的物理路径和 Nginx / 运行时实际读取位置不一致,或者 config/static.php 的 enable 被关掉了却没意识到。
public_path() 返回的路径对不对
Webman 所有静态文件查找都依赖 public_path() 函数返回的绝对路径。这个函数定义在 support/helpers.php 里,默认是 __DIR__.'/../public',但一旦你调整过项目结构(比如把 Webman 当子模块引入、或用了 symlink),它就可能指向错误目录。
验证方法很简单:在任意控制器里临时加一行:
var_dump(public_path()); die;
看输出是否真能定位到你放 upload/avatar.png 的那个 public/ 目录。常见错误包括:
立即学习“PHP免费学习笔记(深入)”;
- 返回路径里混进了多余的
..或拼错了层级,比如变成/var/www/myapp/app/../public实际却该是/var/www/myapp/public - 用了软链接但
realpath()没生效,导致is_file($file)判断失败 - 部署在 Docker 中时,
__DIR__指向容器内路径,而文件实际挂在宿主机其他位置
config/static.php 的 enable 必须为 true
即使 public_path() 正确,如果 config/static.php 里 'enable' => false,整个静态中间件就彻底不干活,所有 /upload/xxx 请求都会直接 404 —— 它连文件存不存在都不检查。
别只看注释,打开文件确认这行是生效的:
'enable' => true,
另外注意:这个配置只在 Webman 自己处理静态请求时起作用(比如用 php start.php start 或 Nginx 反向代理到 Webman HTTP Server)。如果你用的是 Nginx + PHP-FPM,这里反而必须设为 false,否则 Nginx 已经返回了文件,Webman 还会重复处理,浪费 CPU 且可能覆盖响应头。
StaticFile 中间件有没有被加载
config/static.php 里除了 enable,还必须显式声明中间件类:
'middleware' => [support\middleware\StaticFile::class]
漏掉这行,或者写成 app\middleware\StaticFile::class(实际路径是 support\),中间件根本不会注册,enable 再开也没用。
还要检查 support/middleware/StaticFile.php 文件是否存在,以及里面 process() 方法有没有提前 return 掉请求(比如加了未调试完的权限拦截逻辑)。
中文文件名或特殊字符导致路径匹配失败
Webman 原生不自动对 $request->path() 做 urldecode()。访问 /upload/头像.png 时,中间件拿到的是 /upload/%E5%A4%B4%E5%83%8F.png,拼成文件路径后 is_file() 必然返回 false。
修复方式是在 support/middleware/StaticFile.php 的 process() 方法里,在构造文件路径前加解码:
$path = urldecode($request->path());
注意别加在 if (strpos($path, '/.') !== false) 之前,否则绕过隐藏文件检查;也别对整个 $request->path() 无条件解码两次,可能破坏合法编码。
最易被忽略的一点:Nginx 和 Webman 的静态职责必须明确切分。要么全交给 Nginx(此时 Webman 的 static 中间件必须关),要么全交给 Webman 进程(此时 Nginx 不能用 try_files 去 public 目录找文件,得反向代理)。混着用,报错日志里出现 open() "/path/public/api/state" failed 就是典型信号。



















