Detailed description of issue
My static files are hosted on a different subdomain. The iframe src/dest is on the same domain, it’s just the JS files that are on a separate subdomain.
I’m getting the following error:
Uncaught (in promise) Error: Setting up fake worker failed: "Cannot read property 'WorkerMessageHandler' of undefined".
at PDFJSDocumentType.js:960
So the browser is obviously blocking inter-subdomain communication somewhere and returning undefined.
I’ve seen a similar error with PDF.JS when I was setting that up independently once, I needed something like:
PDF.js Express is loaded inside of an iframe, and there are browser iframe restrictions saying that when JS is loaded in an iframe from a separate domain, that JS cannot be interacted with from the parent window (this is why you are seeing that error).
The best solution is to not host the PDF.js Express files on a different domain. However, if this is absolutely necessary, there is a workaround (this is a PDFTron WebViewer guide but it also applies to Express).
So I looked at the iframe src that the pdfjs.express library was creating, and opened that in a tab directly to eliminate the cross tab communication and see whether the error remains. So to be clear that means I’ve got a tab open that is the /core/ui/index.html with the #d= pointing to a PDF file.
I get the same result “Error: Setting up fake worker failed: “Cannot read property ‘WorkerMessageHandler’ of undefined”.”
So the error is happening in PDF.js / Express somewhere, not the interframe communication.
This means the links you’ve posted aren’t relevant as I can’t use postMessage (because there’s no frame involved). It’s just that the /ui/index.html is on a different domain to the scripts it’s loading (because staticfiles are hosted on a different subdomain).
Are you able to tell me more about your environment (browser, server stack, etc)? I assume you have a bit a of a unique environment considering the fact that you cannot load assets from the same domain.
Are you able to send me a link where I can reproduce your issue?
Not unique- I’m not aware of any modern stack that serves static files and dynamic content from the same server any more. Static files are usually compiled using something like webpack and dropped on a static domain (for us this is app-static.onuptick.com) while the app is served from whatever backend end you’re running like Django, etc.
As an example, this site itself (pdfjs.community) has all the static assets served from (discourse-cdn dot com):
I’ll set up an example, I really appreciate the help. Any chance you can email me aidan at uptickhq dot com so I can send you a private link with the details?
The issue is still related to loading assets cross origin. However, this can be resolved by the following:
Remove the <base href="//app-static.onuptick.com/static/pdfjsexpress/public/ui/"> as I believe this will cause weird things to happen internally.
Instantiating Express how it is intended and letting Express set up the iframe, instead of manually importing all the scripts. The iframe is important.
After this, you will still have the issue of cross-origin iframes. To work around this, please use the config option as documented here. Since you are loading the config file from a different domain, you will need to follow this step as well.
After all that your code should look something like this:
import Express from "@pdftron/pdfjs-express";
Express(
{
path: "https://app-static.onuptick.com/static/pdfjsexpress/public",
config: "path/to/config.js"
},
element
)
I am trying to apply the workaround for static files hosted on a separate domain (CDN) and I can’t seem to be able to make it work.
It just crashes with
Uncaught (in promise) Viewer is on a different domain, the promise from WebViewer function is rejected and API functions will not work because of cross domain permissions. See https://www.pdftron.com/kb_cross_origin for more information.
If tried to have config file as well, but it never gets to handling VIEWER_LOADED event:
I believe you did actually have it set up correctly, but your code in the config file is incorrect: you can remove the window.onload as that is redundant. Your code should just look like: