TMSFNCWebbrowser PDF viewing (from memory)

Hi,

I've made a simple test program to view PDF's in the FNC webbrowser component.
Seems to work just fine.

For this, I used the LoadFile method.
We have the PDF's in the database and not in the filesystem.
I could write it to disk and call LoadFile, but due to the sensitive nature of the PDF's and their contents it's undesirable.

Is there a way to load it "from memory" directly into the webbrowser?

Thx.

Hi,

you can use the following technique instead:

procedure TForm1.LoadFromStream(MyStream: TStream);
var
  h: string;
  p: string;
  ms: TMemoryStream;
begin
  p := TTMSFNCUtils.SaveStreamToBase64(MyStream);
  h := '<!DOCTYPE html><html><head></head><body><div>' +
    '<iframe width=100% height=500 src="data:application/pdf;base64,' + p + '">' +
    '</iframe></div></body></html>';
  TMSFNCWebBrowser1.LoadHTML(h);
end;

Thanks Peter for the extremely quick response.
I am definitely gonna try this one out.

1 Like

Hi Pieter,
Just tried your technique and it works great.

The only problem I now encounter is the Height=500 setting.
Unfortunately settting Height=100% doesn't work well.
Is there a way to autosize the Height.
The Width=100% works like a charm.

Thx.

Hi, you can use the following code instead:

  h := '<body style="margin: 0px; padding: 0px;">' +
    '<iframe frameborder="0" scrolling="no" height="100%" width="100%" src="data:application/pdf;base64,' + p + '">' +
    '</iframe></body>';

Looks to be working just great.
Thanks for this solution Pieter.

1 Like

You're welcome!

updated code sample to handle large PDF files

unit Unit29;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.TMSFNCTypes, FMX.TMSFNCUtils, FMX.TMSFNCGraphics, FMX.TMSFNCGraphicsTypes,
  FMX.TMSFNCCustomControl, FMX.TMSFNCWebBrowser, FMX.Controls.Presentation,
  FMX.StdCtrls;

type
  TForm29 = class(TForm)
    TMSFNCWebBrowser1: TTMSFNCWebBrowser;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form29: TForm29;

implementation

{$R *.fmx}

const
  LB = #13#10;

procedure TForm29.Button1Click(Sender: TObject);
var
  p: string;
  ms: TMemoryStream;
  s: string;
begin
  ms := TMemoryStream.Create;
  try
    s := 'setPDFData("%s");';
    ms.LoadFromFile('//PATH TO PDF');
    p := TTMSFNCUtils.SaveStreamToBase64(ms);
    TMSFNCWebBrowser1.ExecuteJavaScript(Format(s, [p]));
  finally
    ms.Free;
  end;
end;

procedure TForm29.FormCreate(Sender: TObject);
var
  h: string;
begin
  h := '<script>' + LB +
         'function base64ToBlob(base64, type = "application/octet-stream") {' + LB +
         '   const binStr = atob(base64);' + LB +
         '   const len = binStr.length;' + LB +
         '   const arr = new Uint8Array(len);' + LB +
         '   for (let i = 0; i < len; i++) {' + LB +
         '     arr[i] = binStr.charCodeAt(i);' + LB +
         '   }' + LB +
         '   return new Blob([arr], { type: type });' + LB +
         '}' + LB +

         'function setPDFData(data){' + LB +
         '  const blob = base64ToBlob(data, ''application/pdf'');' + LB +
         '  const url = URL.createObjectURL(blob);' + LB +
         '  var p = document.getElementById("myPDF");' + LB +
         '  p.src = url;' + LB +
         '}' + LB +
         '</script>' + LB;

  h := h + '<iframe id="myPDF" width="100%" height="100%"/>';
  TMSFNCWebBrowser1.LoadHTML(h);
end;

end.

1 Like