Some test text!

menu
search
Offlinekeyboard_arrow_down

Offline

There are two parts to loading WebViewer in an offline scenario: loading the web resources (e.g. JS, HTML, CSS, Web Workers, etc) and loading the actual document in the viewer. Loading the resources can be accomplished using service worker, AppCache or using local resources embedded in a native app. Then using IndexedDB makes it straightforward to save and load the actual document.

In this guide, we will be using the service worker to cache and serve WebViewer files and localforage to simplify storing and retrieving documents in web storage. This guide assumes you have some basic knowledge about service workers, so you can read this guide for an overview.

To see a complete project with the code in this guide, visit this repo.

linkRegister a service worker

There isn't anything special about registering a service worker for WebViewer. You can follow the exact steps here.

linkCache files

After the service worker has been registered, it's time to cache WebViewer files in the service worker. Depending on the type of the documents you are going to load, not every file needs to be cached. In theory, you will want to cache every file inside the lib folder after unnecessary files have been removed using the optimizing script.

// In your service worker file
const CACHE_NAME = 'YOUR_CACHE_NAME';
// This file is cached only because we are using this library in this guide
const localforage = 'path/to/localforage.js';

// The following files are required to load WebViewer with the default UI
const externalFiles = [
  'path/to/lib/core/external/decode.min.js',
  'path/to/lib/core/external/rawinflate.js',
  'path/to/lib/core/external/pako_inflate.min.js',
  'path/to/lib/core/external/jquery-3.2.1.min.js',
  'path/to/lib/core/external/html2canvas.min.js',
  'path/to/lib/core/external/Promise.js'
];
const uiFiles = [
  'path/to/lib/ui/build/index.html',
  'path/to/lib/ui/build/style.css',
  'path/to/lib/ui/build/webviewer-ui.min.js',
  'path/to/lib/ui/build/i18n/translation-en.json'
];
const webViewerFiles = [
  'path/to/lib/core/CoreControls.js',
  'path/to/lib/webviewer.min.js',
  'path/to/lib/core/CoreWorker.js
];

// The following files are optional

// If you want to load a PDF file
const PDFWorkerFiles = [
  'path/to/lib/core/pdf/pdfnet.res',
  'path/to/lib/core/pdf/PDFworker.js',
  'path/to/lib/core/pdf/lean/PDFNetC.gz.js.mem',
  'path/to/lib/core/pdf/lean/PDFNetC.gz.mem',
  'path/to/lib/core/pdf/lean/PDFNetCWasm.br.js.mem',
  'path/to/lib/core/pdf/lean/PDFNetCWasm.br.wasm',
];
// If you want to load an Office file
const OfficeWorkerFiles = [
  'path/to/lib/core/office/OfficeWorker.js',
  'path/to/lib/core/office/WebOfficeWorker.gz.js.mem',
  'path/to/lib/core/office/WebOfficeWorker.gz.mem',
  'path/to/lib/core/office/WebOfficeWorkerWasm.br.js.mem',
  'path/to/lib/core/office/WebOfficeWorkerWasm.br.wasm',
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        return cache.addAll([
          localforage,
          ...externalFiles,
          ...uiFiles,
          ...webViewerFiles,
          ...PDFWorkerFiles,
          ...OfficeWorkerFiles
        ]);
      })
  );
});

linkReturn cached responses

WebViewer will append a query string when requesting the worker files depending on if you are using the full API. In order for the service worker to return the correct cached files we need to set the ignoreSearch.

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request, { ignoreSearch: true })
      .then(response => {
        if (response) {
          return response;
        }
        return fetch(event.request);
      })
  );
});

linkStore documents

Fetching the document and storing it as a blob are easy using the fetch API and localforage.

const store = localforage.createInstance({
  name: 'store'
});
const filePath = 'path/to/your/file';
const fileName = 'fileName';

fetch(filePath)
  .then(response => response.blob())
  .then(blob => {
    store.setItem(fileName, blob);
  })
  .catch(error => {
    console.log(error);
  });

linkLoad documents

The loadDocument API supports loading a blob so all we need to do is to get the blob from the store and call the API with it.

store
  .getItem(fileName)
  .then((blob) => {
    viewerInstance.loadDocument(blob, {
      filename: fileName
    });
  });

To see a complete project with the code in this guide, visit this repo.

Get the answers you need: Support

close

Free Trial

Get unlimited trial usage of PDFTron SDK to bring accurate, reliable, and fast document processing capabilities to any application or workflow.

Select a platform to get started with your free trial.

Unlimited usage. No email address required.

PDFTron Receives USD$71 Million Growth Investment Led By Silversmith Capital Partners

Learn more
close