Drupal 9/10自定义文件路由遇404问题求助
Drupal 9/10 中 /system/files 路由机制与自定义实现指南
一、/system/files 核心工作流程
核心的/system/files路由是Drupal处理公共文件访问的入口,流程分为三步:
- 路由匹配前置处理:核心的
PathProcessorFiles入站路径处理器会拦截/system/files/xxx/yyy.txt这类路径,提取xxx/yyy.txt作为filepath参数存入请求,同时将路径替换为/system/files,让路由系统能匹配到system.files路由。 - 路由定义:
system.files路由的路径为/system/files/{filepath},其中filepath通过options.parameters.filepath.type: path配置允许包含斜杠,确保多级子目录能被正确识别。 - 控制器逻辑:
FilePublicDownloadController::download()接收filepath参数,加载对应文件实体,校验文件的公开访问权限,最终返回流式响应输出文件内容。
二、自定义路由404问题排查
你已经配置了路径处理器、服务、控制器和路由但仍出现404,大概率是以下环节缺失:
- 路由占位符配置错误:必须在路由的
options里声明filepath的类型为path,否则Drupal会把斜杠当作路由分隔符,无法匹配多级路径。示例路由配置:some.prefix.files: path: '/some/prefix/{filepath}' defaults: _controller: '\Drupal\your_module\Controller\CustomFileDownloadController::download' requirements: _permission: 'access custom file downloads' # 替换为你的自定义权限 options: parameters: filepath: type: 'path' - 路径处理器优先级与逻辑问题:确保你的路径处理器优先级高于核心的
PathProcessorFiles(核心优先级为0,建议设为10),且逻辑正确:将/some/prefix/aaa/bbb.txt替换为/some/prefix,同时把aaa/bbb.txt存入请求属性。示例处理器代码:class CustomPathProcessorFiles implements InboundPathProcessorInterface { public function processInbound($path, Request $request) { $prefix = '/some/prefix/'; if (strpos($path, $prefix) === 0 && strlen($path) > strlen($prefix)) { $filepath = substr($path, strlen($prefix)); $request->attributes->set('filepath', $filepath); return '/some/prefix'; } return $path; } } - 缓存未清空:修改路由或路径处理器后,必须执行
drush cr或通过后台清空缓存,否则旧的路由配置会持续生效。
三、FileDownloadController::download() 参数获取方式
核心控制器的参数获取逻辑很直接:
- 路由占位符直接注入:方法签名
public function download(Request $request, $filepath = '')中的$filepath由路由系统自动注入,对应路径处理器解析后的文件路径。 - Request属性获取:也可以通过
$request->attributes->get('filepath')拿到相同的filepath值,两种方式等价。 - 额外查询参数:如果是私有文件路由,还会通过
$request->query->get('file')获取签名验证参数,但公共文件场景主要依赖filepath参数。
四、扩展为 /some/prefix/{node}/{filepath} 的注意事项
后续扩展带节点ID的路由时,需要注意以下几点:
- 路由实体占位符配置:把
{node}声明为实体类型占位符,让Drupal自动加载节点实体,示例路由:some.prefix.node.files: path: '/some/prefix/{node}/{filepath}' defaults: _controller: '\Drupal\your_module\Controller\CustomNodeFileDownloadController::download' requirements: _entity_access: 'node.view' # 基于节点的访问控制 node: '\d+' options: parameters: node: type: 'entity:node' filepath: type: 'path' - 路径处理器调整:解析路径时要拆分出节点ID和文件路径,比如
/some/prefix/123/aaa/bbb.txt要提取123作为node参数,aaa/bbb.txt作为filepath,并返回/some/prefix/123让路由匹配。 - 双重权限校验:控制器里既要校验文件的访问权限,也要校验当前用户是否有权限查看对应的节点,比如
$node->access('view', \Drupal::currentUser())。
内容的提问来源于stack exchange,提问作者mpj
相关产品推荐
相关产品推荐

