Angular中DomSanitizer与bypassSecurityTrustResourceUrl失效问题
Angular中DomSanitizer和bypassSecurityTrustResourceUrl无效,仍触发NG0904安全错误
错误信息
Error: NG0904: unsafe value used in a resource URL context error properties: Object({ code: 904 }) at sanitizer (node_modules/@angular/core/fesm2022/core.mjs:8735:11) at elementPropertyInternal (node_modules/@angular/core/fesm2022/core.mjs:12432:37) at ɵɵproperty (node_modules/@angular/core/fesm2022/core.mjs:16255:9) at templateFn (ng:///EditHistoryDialogComponent.js:31:9) at executeTemplate (node_modules/@angular/core/fesm2022/core.mjs:12003:13) at refreshView (node_modules/@angular/core/fesm2022/core.mjs:13498:13) at detectChangesInView (node_modules/@angular/core/fesm2022/core.mjs:13663:9) at detectChangesInComponent (node_modules/@angular/core/fesm2022/core.mjs:13638:5) at detectChangesInChildComponents (node_modules/@angular/core/fesm2022/core.mjs:13676:9) at refreshView (node_modules/@angular/core/fesm2022/core.mjs:13548:13)
现有代码
TypeScript代码
fetchFormPage() { const payload = { documentId: this.document_id, }; this.dataService.postRetrieveDocument(payload).subscribe( (response: any) => { this.base64PDF = response.documentContent; const binaryString = window.atob(this.base64PDF); const binaryLen = response.contentLength; const bytes = new Uint8Array(binaryLen); for (let i = 0; i < binaryLen; i++) { bytes[i] = binaryString.charCodeAt(i); } const blob = new Blob([bytes], { type: 'application/pdf' }); this.pdfBlob = blob; this.fileType = this.getDocumentName(this.form_id); this.documentId = 'YourDocumentId'; this.pdfUrl = URL.createObjectURL(blob); this.bypassUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfUrl.toString()) as SafeResourceUrl; this.pdfSrc = bytes; }, (error: any) => { console.error('Error fetching or converting PDF content:', error); } ); }
HTML代码
<div style="margin-top: -5%"> <iframe [src]="bypassUrl" width="100%" height="600px"></iframe> </div>
已尝试方案
- 使用带async的Promise处理Blob URL生成
- 封装返回SafeResourceUrl的独立函数
- 自定义SafePipe处理URL
以上方案均未解决问题。
排查方向与解决方案
确认DomSanitizer注入正确性:检查组件构造函数是否正确注入
DomSanitizer,且所在模块已导入BrowserModule(或BrowserAnimationsModule),示例:constructor(private sanitizer: DomSanitizer) {}延迟iframe渲染避免初始值问题:给
bypassUrl设置初始值为null,并在模板中用*ngIf控制iframe渲染,确保仅当安全URL生成后才加载:<div style="margin-top: -5%" *ngIf="bypassUrl"> <iframe [src]="bypassUrl" width="100%" height="600px"></iframe> </div>简化安全URL生成逻辑:
URL.createObjectURL()返回的本身就是字符串,无需调用toString(),直接传入即可:this.bypassUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfUrl);修复自定义SafePipe(若使用):确保管道正确声明并注入
DomSanitizer,模板中直接使用管道处理原始URL:// 管道代码 import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; @Pipe({ name: 'safeResource' }) export class SafeResourcePipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) {} transform(url: string): SafeResourceUrl { return this.sanitizer.bypassSecurityTrustResourceUrl(url); } }模板中使用:
<iframe [src]="pdfUrl | safeResource" width="100%" height="600px"></iframe>注意需在模块的
declarations数组中添加该管道。手动触发变更检测(OnPush模式下):若组件使用
ChangeDetectionStrategy.OnPush,在订阅完成后手动触发变更检测:import { ChangeDetectorRef } from '@angular/core'; constructor(private sanitizer: DomSanitizer, private cdRef: ChangeDetectorRef) {} // 订阅完成后调用 this.cdRef.detectChanges();
内容的提问来源于stack exchange,提问作者Jekyll and Hyde
相关产品推荐
相关产品推荐

