Angular中sanitize字符串后出现[object Object]问题求助
Angular 17 SSR路由匹配异常与图片Sanitize问题解决
报错信息
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: '%5Bobject%20Object%5D' at Recognizer.noMatchError (d:/TRABAJO/FINAL/front/node_modules/@angular/router/fesm2022/router.mjs:3705:12) at eval (d:/TRABAJO/FINAL/front/node_modules/@angular/router/fesm2022/router.mjs:3738:20) at eval (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/operators/catchError.js:10:39) at OperatorSubscriber.OperatorSubscriber._error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/operators/OperatorSubscriber.js:23:21) at OperatorSubscriber.error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:40:18) at OperatorSubscriber._error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:64:30) at OperatorSubscriber.error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:40:18) at OperatorSubscriber._error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:64:30) at OperatorSubscriber.error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:40:18) at OperatorSubscriber._error (d:/TRABAJO/FINAL/front/node_modules/rxjs/dist/esm/internal/Subscriber.js:64:30) { code: 4002 }
问题场景与相关代码
项目使用Bootstrap轮播展示后端返回的base64格式图片,每张图包含移动端和桌面端版本。首次进入路由时出现上述路由错误,浏览器控制台中img标签的src显示为[object Object];切换页面再返回后恢复正常,不使用sanitize函数时一切正常。
组件构造函数
constructor(private photosService: PhotosService, private petitionsService: PetitionsService) { this.loading = true; this.getCarrusel() afterRender(() => { window.scrollTo(0, 0) this.resizeSubscription = fromEvent(window, 'resize').subscribe(() => { if (window.innerWidth < 749) { this.imgResponsive = true } else { this.imgResponsive = false } }); if (window.innerWidth < 749) { this.imgResponsive = true } else { this.imgResponsive = false } }) }
获取轮播图方法
getCarrusel() { this.photosService.getCarrusel().subscribe((data) => { data.forEach((element: Carrusel) => { element.file = this.petitionsService.sanitizar(element.file) element.fileResponsive = this.petitionsService.sanitizar(element.fileResponsive) }) this.slides = data; }) }
Sanitize处理函数
sanitizar(cadena) { if (cadena) { cadena = this.sanitizer.bypassSecurityTrustUrl(cadena); return cadena } else { return null; } }
浏览器控制台的img标签
<img _ngcontent-ng-c2054693178="" alt="..." class="d-block w-100" src="[object Object]">
原因分析
Angular的bypassSecurityTrustUrl方法返回的是SafeUrl类型的对象,而非原始字符串。在SSR服务器端渲染阶段,直接将该对象绑定到img的src属性时,服务器无法正确解析这个对象,会将其转换为字符串[object Object]。这个异常字符串被路由系统误识别为URL片段,从而触发NG04002路由匹配错误。切换页面后客户端接管渲染,Angular框架能正确处理SafeUrl对象,因此问题消失。
解决方案
方案1:使用自定义Pipe处理安全URL(推荐)
通过Angular管道在模板中处理URL的安全校验,这是符合Angular最佳实践的方式:
- 创建
SafeUrlPipe管道:
import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; @Pipe({ name: 'safeUrl', standalone: true // 独立组件项目需添加此属性 }) export class SafeUrlPipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) {} transform(url: string): SafeUrl | null { return url ? this.sanitizer.bypassSecurityTrustUrl(url) : null; } }
在组件/模块中引入并声明该管道。
修改模板,使用管道处理图片URL:
<!-- 桌面端图片 --> <img [src]="slide.file | safeUrl" class="d-block w-100" alt="轮播图"> <!-- 移动端图片 --> <img [src]="slide.fileResponsive | safeUrl" class="d-block w-100" alt="轮播图">
- 移除
getCarrusel方法中的sanitize处理,保留原始base64字符串:
getCarrusel() { this.photosService.getCarrusel().subscribe((data) => { this.slides = data; }) }
方案2:直接提取SafeUrl的内部值(不推荐)
如果坚持在服务中处理,可以提取SafeUrl对象的内部字符串值(注意:此属性为Angular内部属性,未来版本可能变更):
element.file = this.petitionsService.sanitizar(element.file).changingThisBreaksApplicationSecurity; element.fileResponsive = this.petitionsService.sanitizar(element.fileResponsive).changingThisBreaksApplicationSecurity;
解决图片src的问题后,路由匹配错误会自动消失,因为不再产生[object Object]这种异常URL片段。
内容的提问来源于stack exchange,提问作者Hey L1nk
相关产品推荐
相关产品推荐

