Angular中无法加载pdfjs-dist库,纯JS环境可正常运行
问题描述
使用pdfjs-dist库在Canvas上显示PDF,纯JS环境通过Open Live Server运行完全正常,但迁移到Angular项目后无法加载PDF,报错:
GET http://localhost:4200/node_modules/pdfjs-dist/build/pdf.min.mjs net::ERR_ABORTED 404 (Not Found)
环境版本
"pdfjs-dist": "^4.4.168"- Angular CLI: 16.0.6
- Node: 18.19.0
- Package Manager: npm 10.2.3
纯JS环境正常运行代码
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Render PDF</title> </head> <body> <h2>Render PDF Example</h2> <button id="render-pdf-button">Render PDF</button> <div id="pdf-container"></div> <script type="module" src="./app.js"></script> </body> </html>
myapp.js
import * as pdfjsLib from '/node_modules/pdfjs-dist/build/pdf.min.mjs'; pdfjsLib.GlobalWorkerOptions.workerSrc = '/node_modules/pdfjs-dist/build/pdf.worker.min.mjs'; var PDFAnnotate = function(container_id, url) { var inst = this; this.container_id = container_id; this.url = url; this.renderPDF = function() { var container = document.getElementById(inst.container_id); container.innerHTML = ''; var loadingTask = pdfjsLib.getDocument(inst.url); loadingTask.promise.then(function(pdf) { inst.number_of_pages = pdf.numPages; for (var i = 1; i <= pdf.numPages; i++) { (function(pageNum) { pdf.getPage(pageNum).then(function(page) { var scale = 1.5; var viewport = page.getViewport({ scale: scale }); var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; container.appendChild(canvas); var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); })(i); } }, function(reason) { console.error(reason); }); }; this.initRenderButton = function(button_id) { var button = document.getElementById(button_id); if (button) { button.addEventListener('click', function() { inst.renderPDF(); }); } else { console.error('Button element not found.'); } }; }; var pdfAnnotate = new PDFAnnotate('pdf-container', './output.pdf'); pdfAnnotate.initRenderButton('render-pdf-button');
Angular项目迁移尝试
- 在
src/assets/下创建pdf-renderer文件夹并放入myapp.js,将路径添加至angular.json的scripts标签 - 创建
pdf-rendering组件,代码如下:
pdf-rendering.component.html
<h2>Render PDF Example</h2> <button id="render-pdf-button">Render PDF</button> <div id="pdf-container"></div>
pdf-rendering.component.ts
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-pdf-rendering', templateUrl: './pdf-rendering.component.html', styleUrls: ['./pdf-rendering.component.css'] }) export class PdfRenderingComponent implements OnInit { ngOnInit() { this.loadScript('assets/pdf-renderer/app.js'); } loadScript(src: string) { const script = document.createElement('script'); script.src = src; script.type = 'module'; document.body.appendChild(script); } }
解决方案
原因分析
纯JS环境中Live Server直接暴露项目根目录,/node_modules路径可被浏览器访问;但Angular默认不会将node_modules目录下的文件打包到浏览器可访问的静态资源路径,直接引用该路径会返回404。
方法一:Angular组件直接集成pdfjs-dist(推荐)
符合Angular组件化规范,无需依赖外部脚本:
- 修改
pdf-rendering.component.ts:
import { Component, ViewChild, ElementRef } from '@angular/core'; import * as pdfjsLib from 'pdfjs-dist'; import 'pdfjs-dist/build/pdf.worker.entry'; // 自动加载worker,无需手动设置路径 @Component({ selector: 'app-pdf-rendering', templateUrl: './pdf-rendering.component.html', styleUrls: ['./pdf-rendering.component.css'] }) export class PdfRenderingComponent { @ViewChild('pdfContainer') pdfContainer!: ElementRef; pdfUrl = './assets/output.pdf'; // 将PDF文件放在src/assets目录下 renderPDF() { const container = this.pdfContainer.nativeElement; container.innerHTML = ''; const loadingTask = pdfjsLib.getDocument(this.pdfUrl); loadingTask.promise.then(pdf => { for (let i = 1; i <= pdf.numPages; i++) { (pageNum => { pdf.getPage(pageNum).then(page => { const scale = 1.5; const viewport = page.getViewport({ scale }); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; container.appendChild(canvas); const renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); })(i); } }).catch(reason => { console.error(reason); }); } }
- 修改
pdf-rendering.component.html,使用Angular模板引用变量:
<h2>Render PDF Example</h2> <button (click)="renderPDF()">Render PDF</button> <div #pdfContainer></div>
- 将
output.pdf移动到src/assets目录,确保路径正确。
方法二:配置Angular暴露pdfjs资源(保留外部脚本)
若需继续使用原myapp.js脚本,需配置Angular打包pdfjs资源:
- 修改
angular.json,在assets数组添加pdfjs配置:
"assets": [ "src/favicon.ico", "src/assets", { "glob": "**/*", "input": "./node_modules/pdfjs-dist/build", "output": "./assets/pdfjs/" } ]
- 修改
myapp.js中的导入路径:
import * as pdfjsLib from '/assets/pdfjs/pdf.min.mjs'; pdfjsLib.GlobalWorkerOptions.workerSrc = '/assets/pdfjs/pdf.worker.min.mjs'; // 其余代码保持不变
- 重启
ng serve生效。
内容的提问来源于stack exchange,提问作者Zaryab Ali
相关产品推荐
相关产品推荐

