Ionic6 + Angular15 - Embed PDF

When embedding a PDF in “ion-content” with this code:

  <object data="assets/actualPDFname.pdf" type="application/pdf" width="100%" height="100%">
    <p>It appears you don't have a PDF plugin for this browser.</p>
   </object>

I get to see the PDF perfectly embedded in the page. However, if I use a bas64 string (which is also supposed to work) I get the message:

It appears you don't have a PDF plugin for this browser.

As mentioned in the code block. Can someone tell me why this is happening ?

The result is the same when providing the base64 string through ngOnInit, ngAfterViewInit, wrapped in a promise, …

I must be missing something but I can’t see what.

Any hints are welcome.
Thanks

I haven’t tested it with ionic 6 yet. Using ionic 5 my solution was this: openPdf-ionic5/info.md at 8bd78e26d9ba230f048f67e8d0f4f57c741ff18c · aabuabara/openPdf-ionic5 · GitHub
You can try it.

Use the <object> for embedding PDF should be sufficient for modern browser.

I think root cause of the issue might be the Angular’s XSS protection (Here is the very detailed document: https://angular.io/guide/security)

Long story short, when you try to use an arbitrary value (e.g. base64 string) as the data attribute value of an <object> element, Angular’s XSS protection mechanism will not allow this by default.

To bypass this, the variable for the data attribute must be a Trusting Saft Value typed variable.

In this scenario, the variable should be a SafeResourceUrl, and can be create via bypassSecurityTrustResourceUrl() method from DomSanitizer:

import { Component } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

function convertFileToBase64String(file: File) {
  // skip...
}

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
})
export class AppComponent {
  safePdfBase64String: SafeResourceUrl; // 👈 declare the variable as a SafeResourceUrl

  constructor(private sanitizer: DomSanitizer) {
    // 👇 use Angular's DomSanitizer to transform string value into SafeResourceUrl
    this.safePdfBase64String =
      this.sanitizer.bypassSecurityTrustResourceUrl('');
  }

  async loadPdf(event: Event) {
    const target = event.target as HTMLInputElement;
    const files = target.files as FileList;

    const file = files.item(0);

    if (!file) {
      return;
    }

    const rawPdfBase64String = await convertFileToBase64String(file);

    // 👇 use Angular's DomSanitizer to transform string value into SafeResourceUrl
    this.safePdfBase64String =
      this.sanitizer.bypassSecurityTrustResourceUrl(rawPdfBase64String);
  }
}

Here is a stackblitz playground I made:

You can see the implementaion detail in actions. Hope this is helpful :smile:

Very helpful, Thanks !

1 Like