Angular中点击按钮跳转Embed/IFrame内本地PDF指定页面问题
问题:Base64格式PDF在embed/iframe中点击跳转按钮失效
问题背景
需求:通过<input type="file">获取用户本地PDF文件,转成Base64字符串后,在embed或iframe中展示,支持点击按钮跳转至指定PDF页面。
现状:初始加载时默认跳转指定页面功能正常,但点击跳转按钮时,embed组件变为空白,iframe组件无任何响应。使用Chrome浏览器,无法使用外部类库。
相关原代码:
文件选择处理函数:
onFilesSelected(event: any) { const file = event.target.files[0]; const reader = new FileReader(); reader.onload = () => { this.pdfSrc = reader.result as string this.gotoPage(1) }; reader.onerror = () => { this.hasError = true this.progressText = "File can not be processed." }; reader.readAsDataURL(file); }
页面跳转函数:
gotoPage(page_no: any) { if (typeof (page_no) == 'number') { const url = `${this.pdfSrc}#page=${page_no}`; this.sanitized_url = this._domSanitizer.bypassSecurityTrustResourceUrl(url) } }
跳转按钮代码:
<button (click)="goToPage(5)">Go to Page 5</button> <button (click)="goToPage(10)">Go to Page 10</button> <button (click)="goToPage(15)">Go to Page 15</button>
Embed代码:
<embed [src]="sanitized_url" type="application/pdf" scrolling="auto" height="99%" width="100%" />
IFrame代码:
<iframe id="pdfIframe" [src]="sanitized_url" type="application/pdf" width="100%" height="99%"></iframe>
问题原因
- 按钮绑定错误:按钮点击事件
goToPage与组件内函数gotoPage大小写不一致,导致点击未触发跳转逻辑。 - Chrome对Base64 URL锚点的解析问题:直接修改embed/iframe的
src为带#page=X的Base64 URL时,Chrome无法正确解析这种复合资源标识,导致embed加载失败,iframe因缓存或安全策略不响应。
解决方案
第一步:修正按钮绑定错误
将按钮的点击事件改为与组件函数一致的名称:
<button (click)="gotoPage(5)">Go to Page 5</button> <button (click)="gotoPage(10)">Go to Page 10</button> <button (click)="gotoPage(15)">Go to Page 15</button>
第二步:针对IFrame的跳转修复
利用Chrome内置PDF Viewer的postMessage协议直接控制页面跳转,无需修改src:
gotoPage(page_no: number) { if (typeof page_no !== 'number') return; const iframe = document.getElementById('pdfIframe') as HTMLIFrameElement; if (!iframe?.contentWindow) return; // 向内置PDF Viewer发送跳转指令 iframe.contentWindow.postMessage({ type: 'goToPage', page: page_no }, '*'); }
此方法依赖Chrome内置PDF Viewer的通信协议,在Chrome环境下稳定有效,无需重新加载PDF资源。
第三步:针对Embed的跳转修复
Embed无法通过postMessage控制,需通过销毁并重建Embed元素的方式,让浏览器重新解析带锚点的Base64 URL:
- 修改模板,为Embed添加容器:
<div #embedContainer> <embed [src]="sanitized_url" type="application/pdf" scrolling="auto" height="99%" width="100%" /> </div>
- 修改组件代码,引入
ViewChild并更新跳转函数:
import { ViewChild, ElementRef } from '@angular/core'; // 组件内声明容器引用 @ViewChild('embedContainer') embedContainer!: ElementRef; gotoPage(page_no: number) { if (typeof page_no !== 'number') return; const url = `${this.pdfSrc}#page=${page_no}`; const sanitizedUrl = this._domSanitizer.bypassSecurityTrustResourceUrl(url); const container = this.embedContainer.nativeElement; // 清空容器并创建新Embed元素 container.innerHTML = ''; const embed = document.createElement('embed'); embed.src = sanitizedUrl.changingThisBreaksApplicationSecurity; embed.type = 'application/pdf'; embed.style.height = '99%'; embed.style.width = '100%'; embed.scrolling = 'auto'; container.appendChild(embed); }
通过重建Embed元素,强制浏览器重新加载带锚点的PDF资源,解决直接修改src导致的空白问题。
内容的提问来源于stack exchange,提问作者VIRIYALA NARESH
相关产品推荐
相关产品推荐

