Angular 8中Embed/IFrame加载PDF时API多次调用问题解决
Angular 8中PDF查看器API重复调用问题解决方法
问题根源
你遇到的API重复调用问题,核心原因是Angular的变更检测机制会频繁触发模板中绑定的方法。当你在<embed>的src中直接调用sanitizeURL()时,每次Angular执行变更检测(比如组件初始化、数据更新、甚至PDF加载过程中的DOM变化),都会重新执行这个方法,导致API被反复调用。另外直接绑定未经过安全处理的URL会触发Angular的安全校验错误。
解决方案:预加载+缓存Blob URL
通过提前预加载PDF资源并缓存生成的安全Blob URL,彻底避免模板中频繁调用方法导致的重复请求。
步骤1:组件类实现预加载与缓存逻辑
import { Component, OnInit, OnDestroy } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { FetchTrainingService } from './your-service-path'; // 替换为你的服务路径 @Component({ selector: 'app-pdf-viewer', templateUrl: './pdf-viewer.component.html' }) export class PdfViewerComponent implements OnInit, OnDestroy { // 缓存已处理的PDF安全URL,键为原始API路径 pdfCache: Record<string, string> = {}; baseApiUrl = 'http://localhost:4200/upload/training/getMedia?path='; list: any; // 假设你的PDF路径数据存储在这里 condition_true = false; // 控制显示的条件 constructor( private sanitizer: DomSanitizer, private fetchTraining: FetchTrainingService ) {} ngOnInit(): void { // 假设list数据在组件初始化时已获取,提前加载PDF if (this.list?.path) { this.loadPdf(this.baseApiUrl + this.list.path); } } async loadPdf(fullApiUrl: string): Promise<void> { // 先检查缓存,已存在则直接返回,避免重复请求 if (this.pdfCache[fullApiUrl]) return; try { // 调用API获取Blob数据 const blobData = await this.fetchTraining.getMedia(fullApiUrl).toPromise(); // 生成Blob对象 const pdfBlob = new Blob([blobData], { type: 'application/pdf' }); // 创建Object URL并做安全处理 const safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl( URL.createObjectURL(pdfBlob) ); // 存入缓存 this.pdfCache[fullApiUrl] = safeUrl as string; } catch (error) { console.error('PDF加载失败:', error); } } // 组件销毁时释放Blob URL,防止内存泄漏 ngOnDestroy(): void { Object.values(this.pdfCache).forEach(url => { URL.revokeObjectURL(url); }); } }
步骤2:模板中绑定缓存的安全URL
<div *ngIf="condition_true && pdfCache[baseApiUrl+list.path]"> <embed [src]="pdfCache[baseApiUrl+list.path]" width="500" height="375" type="application/pdf" > </div>
额外说明
- 动态数据处理:如果
list是从API动态获取的,要在数据加载完成后(比如订阅回调中)调用loadPdf方法,确保提前加载PDF资源。 - ng2-pdf-viewer问题排查:如果仍想使用该组件,确认模块中已正确导入
PdfViewerModule:
模板中使用时,直接绑定缓存的安全URL即可:import { PdfViewerModule } from 'ng2-pdf-viewer'; @NgModule({ imports: [PdfViewerModule] }) export class YourModule {}<pdf-viewer [src]="pdfCache[baseApiUrl+list.path]" [render-text]="true" style="display: block;" ></pdf-viewer>
内容的提问来源于stack exchange,提问作者avishekdr
相关产品推荐
相关产品推荐

