PDF.js Read Only is an additional readonly mode for PDF.js, a Portable Document Format (PDF) viewer that is built with HTML5 which is community-driven and supported by Mozilla.
Its purpose to make PDF.js viewer to be readonly mode, including disable right click on mouse (context menu) and several hotkeys (keyboard shortcut) such as:
Ctrl + C
(Copy Text)Ctrl + O
(Open PDF)Ctrl + P
(Print PDF)Ctrl + S
(Save PDF)PrtSc
(Print Screen) (experimental)
A. Desktop
- PDF.js without read only
/generic/web/viewer.html
- If using PDF.js Read Only
/generic/web/viewer_readonly.html
B. Mobile
- PDF.js without read only
/mobile-viewer/viewer.html
- If using PDF.js Read Only
/mobile-viewer/viewer_readonly.html
C. Test
- PDF.js iframe read only
/test/iframe_readonly.html
- PDF.js mobile responsive
/test/mobile_responsive.html
- PDF.js desktop mobile
/test/desktop_mobile.html
A. Desktop
Support Password Protected PDF
-
/generic/web/viewer_readonly.html
adjustment inviewer_readonly.html
<!-- PDF.js Read Only Adjustment --> <!-- <script src="viewer.js"></script> --> <!-- you need to comment or remove this line --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> <!-- adjust your jquery if necessary --> <script src="../../js/pdf.js_readonly.js"></script> <!-- adjust path to pdf.js_readonly.js -->
-
/js/pdf.js_readonly.js
adjustment inpdf.js_readonly.js
// Read Only Preferences var disableRghtClck = true; // Disable Right Click, value: true || false var disableCopyText = true; // Disable Copy Text, value: true || false var disableOpenFile = true; // Disable Open PDF, value: true || false var disablePrintPdf = true; // Disable Print PDF, value: true || false var disableDownload = true; // Disable Save PDF, value: true || false var disablePresents = true; // Disable Presentation, value: true || false var disablePrntScrn = true; // Disable Print Screen, value: true || false (experimental) // Load Specific viewer.js if ( disablePrintPdf ) { $.getScript( '../../js/viewer_noprint.js' ); // Adjust path to viewer_noprint.js if necessary } else { $.getScript( 'viewer.js' ); // Adjust path to viewer.js if necessary }
-
/js/viewer_noprint.js
modification fromviewer.js
/* Modified for PDF.js Read Only * To disable print overlay */ /* window.addEventListener("keydown", function (event) { if (event.keyCode === 80 && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) { window.print(); event.preventDefault(); if (event.stopImmediatePropagation) { event.stopImmediatePropagation(); } else { event.stopPropagation(); } } }, true); */
Note: If you want to create
viewer_noprint.js
on your own fromviewer.js
file of your current PDF.js version, make sure those lines above (or some codes like that) are commented. -
- to
protect
PDF file source
// value: "compressed.tracemonkey-pldi-09.pdf", /* Modified for PDF.js Read Only * It's better to NOT having .PDF extension in the end of file name * This can avoid like IDM to sniff PDF file type automatically download * You also can protect PDF file source from direct access using .htaccess * Or you can never reveal its original file name such as encoding it first! */ value: "compressed.tracemonkey-pldi-09",
- to
allow
access PDF file from different domain
const HOSTED_VIEWER_ORIGINS = ["null", "http://mozilla.github.io", "https://mozilla.github.io", "https://yourdomain.here"];
and makesure the PDF file webserver has HTTP Header
Access-Control-Allow-Origin
, allowing PDF.js viewer domainAccess-Control-Allow-Origin: http(s)://yourPDFjsViewerDomain.here
- to
-
/generic/web/viewer_readonly.html
adjustment inviewer_readonly.html
for custom progress document loading<!-- PDF.js Read Only Adjustment --> <!-- Custom Progress Document Loading --> <div id="customProgress" style="text-align:center;background:#FDFDFB;min-height:95vh"> <img src="https://latuminggi.github.io/pdf.js_readonly/img/documentLoading.gif" /> </div>
including adjustment in
/js/viewer_noprint.js
as you can see on this commit diff -
/generic/web/viewer_readonly.html
to accessfile
from query string (directly from URL)/generic/web/viewer_readonly.html?file={filename.pdf}
For example:
/generic/web/viewer_readonly.html?file=compressed.tracemonkey-pldi-09.pdf
/generic/web/viewer_readonly.html?file={filename}
For example:
/generic/web/viewer_readonly.html?file=compressed.tracemonkey-pldi-09
/generic/web/viewer_readonly.html?file={http(s)://example.com/filename(.pdf)}
B. Mobile
NO Support for Password Protected PDF
-
/mobile-viewer/viewer_readonly.html
adjustment inviewer_readonly.html
<!-- PDF.js Read Only Adjustment --> <!-- <script src="viewer.js"></script> --> <!-- you need to comment or remove this line --> <script src="viewer_mod.js"></script> <!-- adjust path to viewer_mod.js --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> <!-- adjust your jquery if necessary --> <script src="../js/pdf.js_mobile_readonly.js"></script> <!-- adjust path to pdf.js_mobile_readonly.js -->
Note: if you want to enable cache canvas on mobile viewer, you can adjust these lines
<!-- PDF.js Read Only Adjustment --> <!-- <script src="build/pdf.min.js"></script> --> <!-- use pdf(.min).js to enable cache canvas on mobile --> <script src="build/pdf_mod.min.js"></script> <!-- use pdf_mod(.min).js to disable cache canvas on mobile -->
and if you want to access PDF file from different domain, makesure the PDF file webserver has HTTP Header
Access-Control-Allow-Origin
, allowing PDF.js viewer domainAccess-Control-Allow-Origin: http(s)://yourPDFjsViewerDomain.here
-
/js/pdf.js_mobile_readonly.js
adjustment inpdf.js_mobile_readonly.js
// Read Only Preferences var disableRghtClck = true; // Disable Right Click, value: true || false var disableCopyText = true; // Disable Copy Text, value: true || false var disableOpenFile = true; // Disable Open PDF, value: true || false var disablePrintPdf = true; // Disable Print PDF, value: true || false var disableDownload = true; // Disable Save PDF, value: true || false var disablePrntScrn = true; // Disable Print Screen, value: true || false (experimental)
-
/mobile-viewer/viewer_mod.js
modification fromviewer.js
there are 2 differences- first: To enable PDF large image size
/* Modified for PDF.js Read Only * To enable PDF large image size */ // const MAX_IMAGE_SIZE = 1024 * 1024; // Limited Max Image Size const MAX_IMAGE_SIZE = false; // Unlimited Max Image Size
- second: To enable get query string of
file
or using default PDF file
/* Modified for PDF.js Read Only * To enable get query string of file * How can I get query string values in JavaScript? https://stackoverflow.com/a/901144/17754812 */ function getParameterByName(name, url = window.location.href) { name = name.replace(/[\[\]]/g, '\\$&'); var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); } /* Modified for PDF.js Read Only * To get query string of file or using default PDF file */ // const DEFAULT_URL = "web/compressed.tracemonkey-pldi-09.pdf"; // Get PDF file whether from "DEFAULT_URL" or "file" query string var file = getParameterByName('file'); const DEFAULT_URL = (file === null || file === "") ? "web/compressed.tracemonkey-pldi-09" : file;
Note: If you want to create
viewer_mod.js
on your own fromviewer.js
file of your current PDF.js version, make sure those lines above (or some codes like that) are adjusted. -
/mobile-viewer/build/pdf_mod.js
modification frompdf.js
if (this.cache[id] !== undefined) { /* Modified for PDF.js Read Only * To disable cache canvas on mobile */ /* canvasEntry = this.cache[id]; */ canvasEntry = this.canvasFactory.create(width, height); this.canvasFactory.reset(canvasEntry, width, height); canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0); }
Note: If you want to create
pdf_mod.js
on your own frompdf.js
file of your current PDF.js version, make sure those lines above (or some codes like that) are adjusted. -
/mobile-viewer/viewer_readonly.html
adjustment inviewer_readonly.html
for custom progress document loading<!-- PDF.js Read Only Adjustment --> <!-- Custom Progress Document Loading --> <div id="customProgress" style="text-align:center;background:#FFF;min-height:95vh"> <img src="https://latuminggi.github.io/pdf.js_readonly/img/documentLoadingMobile.gif" width="100%" /> </div>
including adjustment in
/mobile-viewer/viewer_mod.js
as you can see on this commit diff -
/mobile-viewer/viewer_readonly.html
to accessfile
from query string (directly from URL)/mobile-viewer/viewer_readonly.html?file=path_to/{filename.pdf}
For example:
/mobile-viewer/viewer_readonly.html?file=web/compressed.tracemonkey-pldi-09.pdf
/mobile-viewer/viewer_readonly.html?file=path_to/{filename}
For example:
/mobile-viewer/viewer_readonly.html?file=web/compressed.tracemonkey-pldi-09
/mobile-viewer/viewer_readonly.html?file={http(s)://example.com/filename(.pdf)}
A. Apache
RewriteEngine on
# only allow from following domain(s):
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example.com*$ [NC]
RewriteRule \.(pdf)$ - [F]
B. Nginx
server {
...
location ~* \.(pdf)$ {
# only allow from following domain(s):
valid_referers example.com www.example.com;
if ($invalid_referer) {
return 403;
}
}
...
}
C. PHP
<?php
$file = '/path/to/file.pdf';
// only allow if specific cookie(s) available, for example:
if ( isset( $_COOKIE['yourCookie'] ) && $_COOKIE['yourCookie'] === 'yourCookieValue' ) {
// only allow from following domain(s), for example:
if ( isset( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'], 'example.com' ) ) {
if ( file_exists($file) ) {
header('Access-Control-Allow-Origin: http(s)://example.com');
/* use HTTP header Content-Type application/octet-stream instead application/pdf
* this can avoid like IDM to sniff PDF file with mime type application/pdf
* and makesure the URL you create does NOT have .pdf extension in the end
*/
header('Content-Type: application/octet-stream');
header('Content-Length: '. filesize($file));
header('Cache-Control: no-cache');
header('Pragma: no-cache');
readfile($file);
exit;
}
}
}