From 2f0b317449674611c12da2463b854d96e5368934 Mon Sep 17 00:00:00 2001 From: leebj Date: Fri, 30 Aug 2024 13:52:18 +0900 Subject: [PATCH] =?UTF-8?q?PDF=ED=8C=8C=EC=9D=BC=20=EB=AF=B8=EB=A6=AC?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EA=B4=80=EB=A0=A8=20=EC=86=8C=EC=8A=A4?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webapp/resources/applib/html/pdf.html | 63 ++++ .../webapp/resources/applib/js/app-support.js | 15 + .../webapp/resources/applib/js/pdfobject.js | 341 ++++++++++++++++++ 3 files changed, 419 insertions(+) create mode 100644 src/main/webapp/resources/applib/html/pdf.html create mode 100644 src/main/webapp/resources/applib/js/pdfobject.js diff --git a/src/main/webapp/resources/applib/html/pdf.html b/src/main/webapp/resources/applib/html/pdf.html new file mode 100644 index 0000000..423ee74 --- /dev/null +++ b/src/main/webapp/resources/applib/html/pdf.html @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +샘플 보기 + + + +
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/resources/applib/js/app-support.js b/src/main/webapp/resources/applib/js/app-support.js index 6e660ea..7e98ec5 100644 --- a/src/main/webapp/resources/applib/js/app-support.js +++ b/src/main/webapp/resources/applib/js/app-support.js @@ -208,6 +208,21 @@ class AppSupport { static sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } + + /************************************************************************** + * PDF파일 미리보기 창 열기 + **************************************************************************/ + static openPDF(blob, windowName){ + + var popup = window.open( + wctx.url("/webjars/applib/html/pdf.html") + ,windowName + ,'top=10, left=10' + ); + popup.onload = () => { + popup.makePdfFromBlob(blob); + }; + } } diff --git a/src/main/webapp/resources/applib/js/pdfobject.js b/src/main/webapp/resources/applib/js/pdfobject.js new file mode 100644 index 0000000..f6738a8 --- /dev/null +++ b/src/main/webapp/resources/applib/js/pdfobject.js @@ -0,0 +1,341 @@ +/** + * PDFObject v2.2.12 + * https://github.com/pipwerks/PDFObject + * @license + * Copyright (c) 2008-2023 Philip Hutchison + * MIT-style license: http://pipwerks.mit-license.org/ + * UMD module pattern from https://github.com/umdjs/umd/blob/master/templates/returnExports.js + */ + +(function (root, factory) { + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof module === "object" && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.PDFObject = factory(); + } +}(this, function () { + + "use strict"; + + //PDFObject is designed for client-side (browsers), not server-side (node) + //Will choke on undefined navigator and window vars when run on server + //Return boolean false and exit function when running server-side + + if( typeof window === "undefined" || + window.navigator === undefined || + window.navigator.userAgent === undefined || + window.navigator.mimeTypes === undefined){ + return false; + } + + let pdfobjectversion = "2.2.12"; + let nav = window.navigator; + let ua = window.navigator.userAgent; + + //Time to jump through hoops -- browser vendors do not make it easy to detect PDF support. + + /* + IE11 still uses ActiveX for Adobe Reader, but IE 11 doesn't expose window.ActiveXObject the same way + previous versions of IE did. window.ActiveXObject will evaluate to false in IE 11, but "ActiveXObject" + in window evaluates to true. + + MS Edge does not support ActiveX so this test will evaluate false + */ + let isIE = ("ActiveXObject" in window); + + /* + There is a coincidental correlation between implementation of window.promises and native PDF support in desktop browsers + We use this to assume if the browser supports promises it supports embedded PDFs + Is this fragile? Sort of. But browser vendors removed mimetype detection, so we're left to improvise + */ + let isModernBrowser = (window.Promise !== undefined); + + //Older browsers still expose the mimeType + let supportsPdfMimeType = (nav.mimeTypes["application/pdf"] !== undefined); + + //Safari on iPadOS doesn't report as 'mobile' when requesting desktop site, yet still fails to embed PDFs + let isSafariIOSDesktopMode = ( nav.platform !== undefined && + nav.platform === "MacIntel" && + nav.maxTouchPoints !== undefined && + nav.maxTouchPoints > 1 ); + + //Quick test for mobile devices. + let isMobileDevice = (isSafariIOSDesktopMode || /Mobi|Tablet|Android|iPad|iPhone/.test(ua)); + + //Safari desktop requires special handling + let isSafariDesktop = ( !isMobileDevice && + nav.vendor !== undefined && + /Apple/.test(nav.vendor) && + /Safari/.test(ua) ); + + //Firefox started shipping PDF.js in Firefox 19. If this is Firefox 19 or greater, assume PDF.js is available + let isFirefoxWithPDFJS = (!isMobileDevice && /irefox/.test(ua) && ua.split("rv:").length > 1) ? (parseInt(ua.split("rv:")[1].split(".")[0], 10) > 18) : false; + + + /* ---------------------------------------------------- + Supporting functions + ---------------------------------------------------- */ + + let createAXO = function (type){ + var ax; + try { + ax = new ActiveXObject(type); + } catch (e) { + ax = null; //ensure ax remains null + } + return ax; + }; + + //If either ActiveX support for "AcroPDF.PDF" or "PDF.PdfCtrl" are found, return true + //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed + let supportsPdfActiveX = function (){ return !!(createAXO("AcroPDF.PDF") || createAXO("PDF.PdfCtrl")); }; + + //Determines whether PDF support is available + let supportsPDFs = ( + //As of Sept 2020 no mobile browsers properly support PDF embeds + !isMobileDevice && ( + //We're moving into the age of MIME-less browsers. They mostly all support PDF rendering without plugins. + isModernBrowser || + //Modern versions of Firefox come bundled with PDFJS + isFirefoxWithPDFJS || + //Browsers that still support the original MIME type check + supportsPdfMimeType || + //Pity the poor souls still using IE + (isIE && supportsPdfActiveX()) + ) + ); + + //Create a fragment identifier for using PDF Open parameters when embedding PDF + let buildURLFragmentString = function(pdfParams){ + + let string = ""; + let prop; + + if(pdfParams){ + + for (prop in pdfParams) { + if (pdfParams.hasOwnProperty(prop)) { + string += encodeURIComponent(prop) + "=" + encodeURIComponent(pdfParams[prop]) + "&"; + } + } + + //The string will be empty if no PDF Params found + if(string){ + + string = "#" + string; + + //Remove last ampersand + string = string.slice(0, string.length - 1); + + } + + } + + return string; + + }; + + let embedError = function (msg, suppressConsole){ + if(!suppressConsole){ + console.log("[PDFObject] " + msg); + } + return false; + }; + + let emptyNodeContents = function (node){ + while(node.firstChild){ + node.removeChild(node.firstChild); + } + }; + + let getTargetElement = function (targetSelector){ + + //Default to body for full-browser PDF + let targetNode = document.body; + + //If a targetSelector is specified, check to see whether + //it's passing a selector, jQuery object, or an HTML element + + if(typeof targetSelector === "string"){ + + //Is CSS selector + targetNode = document.querySelector(targetSelector); + + } else if (window.jQuery !== undefined && targetSelector instanceof jQuery && targetSelector.length) { + + //Is jQuery element. Extract HTML node + targetNode = targetSelector.get(0); + + } else if (targetSelector.nodeType !== undefined && targetSelector.nodeType === 1){ + + //Is HTML element + targetNode = targetSelector; + + } + + return targetNode; + + }; + + let generatePDFObjectMarkup = function (embedType, targetNode, url, pdfOpenFragment, width, height, id, title, omitInlineStyles, customAttribute, PDFJS_URL){ + + //Ensure target element is empty first + emptyNodeContents(targetNode); + + let source = url; + + if(embedType === "pdfjs"){ + //If PDFJS_URL already contains a ?, assume querystring is in place, and use an ampersand to append PDFJS's file parameter + let connector = (PDFJS_URL.indexOf("?") !== -1) ? "&" : "?"; + source = PDFJS_URL + connector + "file=" + encodeURIComponent(url) + pdfOpenFragment; + } else { + source += pdfOpenFragment; + } + + let el_type = (embedType === "pdfjs" || embedType === "iframe") ? "iframe" : "embed"; + let el = document.createElement(el_type); + + el.className = "pdfobject"; + el.type = "application/pdf"; + el.title = title; + el.src = source; + + if(id){ + el.id = id; + } + + if(el_type === "iframe"){ + el.allow = "fullscreen"; + el.frameborder = "0"; + } + + if(!omitInlineStyles){ + + let style = (el_type === "embed") ? "overflow: auto;" : "border: none;"; + + if(targetNode !== document.body){ + //assign width and height to target node + style += "width: " + width + "; height: " + height + ";"; + } else { + //this is a full-page embed, use CSS to fill the viewport + style += "position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%;"; + } + + el.style.cssText = style; + + } + + //Allow developer to insert custom attribute on embed/iframe element, but ensure it does not conflict with attributes used by PDFObject + let reservedTokens = ["className", "type", "title", "src", "style", "id", "allow", "frameborder"]; + if(customAttribute && customAttribute.key && reservedTokens.indexOf(customAttribute.key) === -1){ + el.setAttribute(customAttribute.key, (typeof customAttribute.value !== "undefined") ? customAttribute.value : ""); + } + + targetNode.classList.add("pdfobject-container"); + targetNode.appendChild(el); + + return targetNode.getElementsByTagName(el_type)[0]; + + }; + + let embed = function(url, targetSelector, options){ + + //If targetSelector is not defined, convert to boolean + let selector = targetSelector || false; + + //Ensure options object is not undefined -- enables easier error checking below + let opt = options || {}; + + //Get passed options, or set reasonable defaults + let id = (typeof opt.id === "string") ? opt.id : ""; + let page = opt.page || false; + let pdfOpenParams = opt.pdfOpenParams || {}; + let fallbackLink = (typeof opt.fallbackLink === "string" || typeof opt.fallbackLink === "boolean") ? opt.fallbackLink : true; + let width = opt.width || "100%"; + let height = opt.height || "100%"; + let title = opt.title || "Embedded PDF"; + let assumptionMode = (typeof opt.assumptionMode === "boolean") ? opt.assumptionMode : true; + let forcePDFJS = (typeof opt.forcePDFJS === "boolean") ? opt.forcePDFJS : false; + let supportRedirect = (typeof opt.supportRedirect === "boolean") ? opt.supportRedirect : false; + let omitInlineStyles = (typeof opt.omitInlineStyles === "boolean") ? opt.omitInlineStyles : false; + let suppressConsole = (typeof opt.suppressConsole === "boolean") ? opt.suppressConsole : false; + let forceIframe = (typeof opt.forceIframe === "boolean") ? opt.forceIframe : false; + let PDFJS_URL = opt.PDFJS_URL || false; + let targetNode = getTargetElement(selector); + let fallbackHTML = ""; + let pdfOpenFragment = ""; + let customAttribute = opt.customAttribute || {}; + let fallbackHTML_default = "

This browser does not support inline PDFs. Please download the PDF to view it: Download PDF

"; + + //Ensure URL is available. If not, exit now. + if(typeof url !== "string"){ return embedError("URL is not valid", suppressConsole); } + + //If target element is specified but is not valid, exit without doing anything + if(!targetNode){ return embedError("Target element cannot be determined", suppressConsole); } + + //page option overrides pdfOpenParams, if found + if(page){ pdfOpenParams.page = page; } + + //Stringify optional Adobe params for opening document (as fragment identifier) + pdfOpenFragment = buildURLFragmentString(pdfOpenParams); + + + // --== Do the dance: Embed attempt #1 ==-- + + //If the forcePDFJS option is invoked, skip everything else and embed as directed + if(forcePDFJS && PDFJS_URL){ + return generatePDFObjectMarkup("pdfjs", targetNode, url, pdfOpenFragment, width, height, id, title, omitInlineStyles, customAttribute, PDFJS_URL); + } + + // --== Embed attempt #2 ==-- + + //Embed PDF if traditional support is provided, or if this developer is willing to roll with assumption + //that modern desktop (not mobile) browsers natively support PDFs + if(supportsPDFs || (assumptionMode && !isMobileDevice)){ + + //Should we use or