Section:

Run without Viewer in Salesforce

Apryse's SDK provides full viewing of documentation formats and other capabilities but also provides access to Apryse's PDFNet SDK that allows document operations excluding a UI if necessary.

This is useful for Salesforce that needs additional processing without viewing a document. Although there are performance drawbacks as this is done on the client-side, it can be critical as part of your app's flow.

Here is a sample no-viewer Salesforce to follow with this guide:

Prerequisites

This guide assumes you will have downloaded WebViewer SDK and have Webviewer running on your Salesforce org.

If you have not done so, please check out the following to get started:

1. Create a hidden LWC

Webviewer still needs to be present on the page of your Salesforce org. You will need to create a lightning web component that has a hidden div to hold the iframe that would run no-viewer Webviewer.

HTML

1<template>
2 <div id="core-controls-iframe" class="slds-hidden" lwc:dom="manual"></div>
3</template>

WebViewer Core is the core for WebViewer. The usual script that would be required with the UI is webviewer.min.js. Using this script would automatically import and use the core.

JavaScript

1renderedCallback() {
2 Promise.all([loadScript(this, libUrl + '/webviewer.min.js')])
3 .then(() => {
4 this.initUI();
5 })
6 .catch(console.error);
7 }

webviewerConstructor is similar to custom tag in a Webviewer constructor, pass information through the iframe src and hash the information from the url in the config file. Set the iframe to take up no space in the lwc if you want a true no-viewer page. Create an iframe to host an html file that runs script tags pathed to webviewer.core.min.js and PDFNet.js

JavaScript

1var webviewerConstructor = {
2 cs_pdftron_core: libUrl + "/core/webviewer-core.min.js",
3 pdfnet: myfilesUrl + "/PDFNet.js",
4 full_api: true
5};
6
7initUI() {
8 const viewerElement = this.template.querySelector("div");
9 var queryParameter = `#param=${JSON.stringify( webviewerConstructor )}`;
10
11 var rcFrame = document.createElement("iframe");
12 rcFrame.style = "position: absolute; width:0; height:0; border:0;";
13
14 rcFrame.src = `${myfilesUrl}/noviewer.html${queryParameter}`;
15 viewerElement.appendChild(rcFrame);
16 this.iframeWindow = rcFrame.contentWindow;
17}

2. Setting the worker path

In a viewer-less scenario, we would only import the core script (webviewer-core.min.js; CoreControls.js prior to WebViewer 8.0) in the HTML, if needing the FULL api you need to reference a different script(PDFNet.js) also.

JavaScript

1var script = document.createElement('script');
2 script.onload = function () {
3 init();
4 var pdfnet = document.createElement('script');
5 pdfnet.src = clientSidePdfGenerationConfig['pdfnet'];
6 document.head.appendChild(pdfnet);
7 };
8 script.src = clientSidePdfGenerationConfig['cs_pdftron_core'];
9 document.head.appendChild(script);

WebViewer requires web workers to function and work with documents. This is necessary regardless of the setup. Normally, this is done automatically via the path option in the WebViewer constructor. In a viewer-less scenario, we can load the workers with a simple JavaScript call:

JavaScript

1window.Core.forceBackendType('ems');
2
3window.Core.setOfficeAsmPath(resourceURL + 'office_asm');
4window.Core.setOfficeWorkerPath(resourceURL + 'office');
5window.Core.setOfficeResourcePath(resourceURL + 'office_resource');
6
7// pdf workers
8window.Core.setPDFResourcePath(resourceURL + 'resource');
9if (clientSidePdfGenerationConfig['full_api']) {
10 window.Core.setPDFWorkerPath(resourceURL + 'pdf_full');
11 window.Core.setPDFAsmPath(resourceURL + 'asm_full');
12} else {
13 window.Core.setPDFWorkerPath(resourceURL + 'pdf_lean');
14 window.Core.setPDFAsmPath(resourceURL + 'asm_lean');
15}
16
17// external 3rd party libraries
18window.Core.setExternalPath(resourceURL + 'external');
19window.Core.disableEmbeddedJavaScript(true)
20
21window.Core.disableOptimizedWorkers();

3. Usage

Once the workers are ready, everything is in place to use the APIs and classes in the Core namespace.

Communicate with Salesforce

Often in Salesforce, sending information to our workers is common so having a communication method to recieve and send out information is required.

JavaScript

1// Recieve
2window.addEventListener("message", receiveMessage, false);
3
4function receiveMessage(event) {
5 if (event.isTrusted && typeof event.data === 'object') {
6 switch (event.data.type) {
7 case 'DOWNLOAD_DOCUMENT':
8 transportDocument(event.data.payload, false)
9 break;
10 default:
11 break;
12 }
13 }
14}
15
16// Send
17parent.postMessage({ type: 'DOWNLOAD_DOCUMENT', file }, '*')

Building a custom UI

One special use case would be to create your own UI by leveraging the DocumentViewer class and object.

1const documentViewer = new Core.DocumentViewer();
2
3// Hook up the DocumentViewer object to your own elements
4documentViewer.setScrollViewElement(document.getElementById('scroll-view'));
5documentViewer.setViewerElement(document.getElementById('viewer'));
6
7// Load your document
8documentViewer.loadDocument('path/to/document.pdf', { l: licenseKey });

You can check out the full guide on how to build your own UI .

Processing documents (Full API - PDFNet)

Another use case is to use the APIs to process documents in the client (browser). We already establish Full API usage so now we just have to test them.

1async function main() {
2 // creates an empty pdf document (PDFDoc)
3 const doc = await PDFNet.PDFDoc.create();
4 doc.initSecurityHandler();
5 // Locks all operations on the document
6 doc.lock();
7
8 // insert user code after this point
9 const pgnum = await doc.getPageCount();
10 alert(`Test Complete! Your file has ${pgnum} pages`);
11};
12
13PDFNet.runWithCleanup(main, /* License key goes here after purchase */)

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales