Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork3k
Embedding PDF.JS in CEFSharp
PDF.JS is Mozilla's open source PDF renderer, availablehere. The same one that is used in Firefox.
- Has a complete API for manipulating the viewer and PDF, accessible from javascript.
- All loaded from local HTML, CSS and JS files, so can be easily modified.
- Page navigation from the index is added to browser history
- Restores last scroll position when revisiting the document
- unzip pdf.js in a convenient folder for your project
- Add a sub folder to download and read PDFs
- Register the folder in a custom scheme handler
- Add javascript to post message when viewer loaded
- disable the default PDF extension in CEFSharp
- Disable default handling so PDFs trigger a download
- Use download and request handlers to trigger PDF handling
- Download PDF to sub folder of the custom scheme
- After
isComplete, load PDF.JS viewer from custom scheme
The PDF.JS viewer is loaded with a query string of the local scheme url and PDF url e.gpdfjs://viewer/web/viewer.html?file=pdfjs://viewer/cache/pdffile.pdf&url=https://original.com/pdffile.pdf.
The query parameter file is used by the viewer, url is used to provide the PDF url.
This means that on reload and history navigation, the PDF will be loaded from the custom scheme, as expected.
If you want to reload from the server, you would need to implement your ownReload(IgnoreCache) method.
Example folder structure with cache folder added for PDF downloads:
build pdf.js codecache add folder for PDFsweb pdf.js viewerFriendPDFEnabledAsBooleanFriendPDFCachePathAsStringFriendSubRegisterPDFJS(ByRefSettingsAsCefSettings,RootPathAsString)'Disable default handling - PDFs will be downloadedSettings.CefCommandLineArgs.Add("disable-pdf-extension")DimSchemeAsNewCefCustomSchemeScheme.SchemeName="pdfjs"Scheme.DomainName="viewer"Scheme.SchemeHandlerFactory=NewSchemeHandler.FolderSchemeHandlerFactory(RootPath)Settings.RegisterScheme(Scheme)PDFCachePath= $"{RootPath}\cache\"PDFEnabled=TrueEndSub
'Set download and request handlersBrowser.DownloadHandler=MeBrowser.RequestHandler=Me' Locals to control PDF download and viewingPrivatePDFCacheUrlAsString=""PrivatePDFSavePathAsString=""PrivateSubOnBeforeDownload(chromiumWebBrowserAsIWebBrowser,browserAsIBrowser,downloadItemAsDownloadItem,callbackAsIBeforeDownloadCallback)ImplementsIDownloadHandler.OnBeforeDownloadIfPDFIsDownload(downloadItem)Then'Probably want to use an MD5 file name herePDFSavePath= $"{PDFCachePath}{downloadItem.SuggestedFileName}"PDFCacheUrl= $"pdfjs://viewer/cache/{downloadItem.SuggestedFileName}"callback.Continue(PDFSavePath,False)EndIfEndSubPrivateSubOnDownloadUpdated(chromiumWebBrowserAsIWebBrowser,browserAsIBrowser,downloadItemAsDownloadItem,callbackAsIDownloadItemCallback)ImplementsIDownloadHandler.OnDownloadUpdatedIfPDFIsDownload(downloadItem)ThenIfdownloadItem.IsCompleteThenchromiumWebBrowser.LoadUrl($"pdfjs://viewer/web/viewer.html?file={PDFCacheUrl}&url={downloadItem.Url}")EndIfEndIfEndSub' Is the download a PDF?PrivateFunctionPDFIsDownload(ItemAsDownloadItem)AsBooleanReturnPDFEnabledAndItem.MimeType="application/pdf"AndNotItem.Url.StartsWith("blob")EndFunction
You can provide the original PDF url, derived from the query of the custom scheme url. e.g.
ReadonlyPropertyAddress()AsStringGetReturnIf(Browser.Address.StartsWith("pdfjs"),Browser.Address.split("=").Last,Browser.Address)EndGetEndProperty
- Handle IsCancelled and IsValid properties in DownloadItem
- Keep reference to callback handler to cancel download externally
- Implement stop and reload with IgnoreCache commands