Search code examples
javascriptangulartypescriptangular11pdf.js

create pdf thumbnail with pdfjs in angular 11


I want to show the first page of a pdf file as an image. As far as I can see, I can´t do that with the typescript library "ng2-pdf-viewer" and therefore need to use the javascript library "pdfjs-dist". I found this post describing how to create a thumbnail with pdfjs.

On "ng serve" I get the following error message:

Error: ./node_modules/pdfjs-dist/build/pdf.js 2205:45
Module parse failed: Unexpected token (2205:45)
File was processed with these loaders:
 * ./node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js
 * ./node_modules/@ngtools/webpack/src/ivy/index.js
You may need an additional loader to handle the result of these loaders.
|         intent: renderingIntent,
|         renderInteractiveForms: renderInteractiveForms === true,
>         annotationStorage: annotationStorage?.serializable || null
|       });
|     }

I found this post describing how to solve this by changing the angular builder. Then however I get the following error:

TypeError: Cannot read property 'flags' of undefined

I can only find mentions of this error in angular 9.

Therefore my questions:

  • Is it really necessary to use a custom builder?
  • How can I fix "Cannot read property 'flags'" in angular 11?

I´m using the following dependencies:

  "dependencies": {
    "@angular/animations": "~11.2.13",
    "@angular/common": "~11.2.13",
    "@angular/compiler": "~11.2.13",
    "@angular/core": "~11.2.13",
    "@angular/forms": "~11.2.13",
    "@angular/platform-browser": "~11.2.13",
    "@angular/platform-browser-dynamic": "~11.2.13",
    "@angular/router": "~11.2.13",
    "@types/pdfjs-dist": "^2.7.4",
    "pdfjs-dist": "^2.8.335",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.3"
  },

Solution

  • I was able to solve this myself after updating angular to version 12.2.4:

    import { Injectable } from '@angular/core';
    import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
    import { from, Observable } from 'rxjs';
    import { map, switchMap, take } from 'rxjs/operators';
    import { getDocument, GlobalWorkerOptions, version } from 'pdfjs-dist';
    
    @Injectable({
      providedIn: 'root'
    })
    export class DocumentService {
      constructor(private sanitizer: DomSanitizer) {
        GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${version}/pdf.worker.min.js`;
      }
    
      public getPdfThumbnail(pdfUrl: string) {
        return from(getDocument(pdfUrl).promise)
        .pipe(
          take(1),
          switchMap(pdf => from(pdf.getPage(1))),
          switchMap(page => {
            const canvas = document.createElement('canvas');
            const viewport = page.getViewport({ scale: 2 });
            canvas.height = viewport.height;
            canvas.width = viewport.width;
    
            return from(page.render({
              canvasContext: canvas.getContext('2d') as CanvasRenderingContext2D,
              viewport
            }).promise)
            .pipe(
              map(() => canvas)
            );
          }),
          switchMap(canvas => {
            return new Observable<SafeUrl>(observer => {
              canvas.toBlob(blob => {
                if (blob) {
                  observer.next(this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(blob)));
                  observer.complete();
                }
              }, 'image/jpeg', 0.75);
            });
          })
        );
      }
    }