如何在Symfony控制器中返回带版本的资源作为响应?
解决控制器中返回AssetMapper版本化资源的问题
错误原因
你之前的代码报错是因为Asset->getUrl()返回的是Web可访问的URL(比如/images/logo/logo-full.webp),而$this->file()方法需要的是服务器本地的文件路径,直接传入URL自然会触发FileNotFoundException。另外,你使用的EmptyVersionStrategy也没有利用AssetMapper的版本化机制,完全不符合需求。
正确解决方案
要在控制器中实现和Twigasset()函数一致的效果,需要借助AssetMapperInterface服务来获取版本化资源的真实本地路径,并配置正确的缓存头:
1. 注入AssetMapper服务
在控制器方法中注入AssetMapperInterface,它是AssetMapper组件的核心服务,负责资源的映射与版本化管理。
2. 获取资源的本地路径
通过findAsset()方法定位资源,再拼接项目根目录与资源的公共路径,得到本地文件的真实路径。
3. 返回带缓存策略的响应
设置与AssetMapper默认行为一致的缓存头,利用浏览器长期缓存版本化资源。
完整代码示例:
use Symfony\Component\AssetMapper\AssetMapperInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class YourController extends AbstractController { public function logo(AssetMapperInterface $assetMapper): BinaryFileResponse { // 定位资源:路径相对于项目的assets/目录 $asset = $assetMapper->findAsset('images/logo/logo-full.webp'); // 拼接得到服务器本地的真实文件路径 $localFilePath = $this->getParameter('kernel.project_dir') . '/public' . $asset->getPublicPath(); // 返回文件并配置缓存策略 $response = $this->file($localFilePath); $response->setPublic(); $response->setMaxAge(31536000); // 1年长期缓存 $response->headers->addCacheControlDirective('immutable', true); return $response; } }
关键说明
- 资源路径:
findAsset()接收的路径是相对于assets/目录的,确保你的资源实际存放在assets/images/logo/下(AssetMapper会自动处理版本化并复制到public/assets/目录)。 - 版本化效果:
$asset->getPublicPath()会返回带哈希后缀的路径(比如/assets/images/logo/logo-full.abc123.webp),和Twigasset()生成的URL完全一致。 - 缓存策略:设置
immutable和长缓存时间,是因为版本化资源的哈希会随内容变化而更新,无需担心缓存过期问题。
内容的提问来源于stack exchange,提问作者user18482403
相关产品推荐
相关产品推荐

