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

如何在Angular中展示本地PDF文件并实现打印功能?

Solution for Displaying and Printing Local PDFs in Angular

Hey there! I totally get the frustration here—trying to load local PDFs directly in Angular runs straight into browser security restrictions, which is why your iframe approach is throwing errors. Let’s break down the best ways to solve this:

Why the iframe approach fails

Browsers block web apps (running on http://localhost or a server) from accessing local file:// URLs due to same-origin policy and security safeguards. Even if you use a third-party viewer like Google Drive, it can’t access files on your local filesystem either.


The most secure and reliable way is to have users upload the PDF file directly to your Angular app. You can then use PDF.js (a popular open-source PDF rendering library) to display it in the browser, and add custom print functionality. Here’s a step-by-step implementation:

Step 1: Install dependencies

First, add PDF.js and its TypeScript types to your project:

npm install pdfjs-dist
npm install @types/pdfjs-dist --save-dev

Step 2: Component Template (app.component.html)

Add a file input, a container for PDF pages, and a print button:

<input type="file" accept=".pdf" (change)="onFileSelected($event)" class="pdf-upload">
<div #pdfContainer class="pdf-container"></div>
<button (click)="printPDF()" [disabled]="!pdfLoaded" class="print-btn">Print PDF</button>

Step 3: Component Logic (app.component.ts)

Implement file reading, PDF rendering, and print functionality:

import { Component, ViewChild, ElementRef } from '@angular/core';
import * as pdfjsLib from 'pdfjs-dist';
import { PDFDocumentProxy } from 'pdfjs-dist';

// Set PDF.js worker source (use a CDN or local file)
pdfjsLib.GlobalWorkerOptions.workerSrc = '//cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('pdfContainer') pdfContainer!: ElementRef;
  pdfLoaded = false;
  renderedPages: HTMLCanvasElement[] = [];

  onFileSelected(event: Event): void {
    const file = (event.target as HTMLInputElement).files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = async (e) => {
      const arrayBuffer = e.target?.result as ArrayBuffer;
      const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
      this.renderedPages = [];
      this.pdfContainer.nativeElement.innerHTML = '';

      // Render each PDF page to a canvas element
      for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        const viewport = page.getViewport({ scale: 1.2 }); // Adjust scale for readability
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d')!;
        
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        
        await page.render({
          canvasContext: context,
          viewport: viewport
        }).promise;
        
        this.pdfContainer.nativeElement.appendChild(canvas);
        this.renderedPages.push(canvas);
      }

      this.pdfLoaded = true;
    };
    reader.readAsArrayBuffer(file);
  }

  printPDF(): void {
    const printWindow = window.open('', '_blank');
    if (!printWindow) return;

    printWindow.document.write(`
      <html>
        <head>
          <title>Print PDF</title>
          <style>
            body { margin: 0; padding: 1rem; }
            canvas { display: block; margin: 0 auto; max-width: 100%; }
          </style>
        </head>
        <body>
    `);

    // Add all rendered pages to the print window
    this.renderedPages.forEach(page => {
      printWindow.document.write(page.outerHTML);
    });

    printWindow.document.write('</body></html>');
    printWindow.document.close();
    
    // Trigger print after the content loads
    setTimeout(() => printWindow.print(), 300);
  }
}

Step 4: Basic Styling (app.component.css)

.pdf-upload {
  margin: 1rem 0;
  padding: 0.5rem;
}

.pdf-container {
  margin: 1rem 0;
  min-height: 400px;
}

.print-btn {
  padding: 0.5rem 1.5rem;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.print-btn:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

Alternative: Browser Security Workaround (Testing Only)

If you’re building an internal tool in a fully trusted environment and need to load local PDFs without user upload, you can disable browser security restrictions. This is NOT recommended for production as it exposes users to security risks:

For Chrome/Edge:

Close all browser instances, then launch it with these flags:

chrome.exe --allow-file-access-from-files --disable-web-security

Then you can use an iframe with the local file path:

<iframe src="file:///C:/Users/xx/Desktop/xyz.pdf" frameBorder="0" scrolling="auto" height="100%" width="100%"></iframe>

Again, this is strictly for testing—never use this for public-facing apps.


Final Notes

The user upload approach is the only way to comply with modern browser security standards and work reliably across all environments. It gives you full control over rendering and printing, and avoids any cross-origin or file access errors.

内容的提问来源于stack exchange,提问作者ozer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:57:33