You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 04:05:42