pdfjs-vue-print
Version:
Example Vue 3 project using pdf.js to build a simple custom PDF.js viewer and print service.
282 lines (239 loc) • 7.32 kB
JavaScript
/* Copyright 2016 Mozilla Foundation
* Copyright 2022 Drew Letcher
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
import * as pdfjsLib from "pdfjs-dist/build/pdf.js"
import * as pdfjsViewer from "pdfjs-dist/web/pdf_viewer.js"
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
// eslint-disable-next-line no-alert
alert("Please build the pdfjs-dist library using\n `gulp dist-install`");
}
pdfjsLib.GlobalWorkerOptions.workerSrc = "../../node_modules/pdfjs-dist/build/pdf.worker.js";
const USE_ONLY_CSS_ZOOM = true;
const TEXT_LAYER_MODE = 0; // DISABLE
const MAX_IMAGE_SIZE = 1024 * 1024;
const CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
const CMAP_PACKED = true;
const DEFAULT_SCALE_DELTA = 1.1;
const MIN_SCALE = 0.25;
const MAX_SCALE = 10.0;
const DEFAULT_SCALE_VALUE = "auto";
const ENABLE_XFA = false;
export default class PDFViewerApp {
constructor(options) {
this.options = options;
this.viewerContainer = options.viewerContainer || null;
this.password = options.password || "";
this.eventBus = null;
this._boundEvents = {};
this.l10n = pdfjsViewer.NullL10n;
this.pdfViewer = null;
this.pdfDocument = null;
this.pdfLoadingTask = null;
this.url = "";
this.documentInfo = null;
this.metadata = null;
}
/**
*
* @returns
*/
createViewer() {
console.log("createViewer");
this.eventBus = new pdfjsViewer.EventBus();
const pdfViewer = new pdfjsViewer.PDFViewer({
container: this.viewerContainer,
eventBus: this.eventBus,
l10n: this.l10n,
useOnlyCssZoom: USE_ONLY_CSS_ZOOM,
textLayerMode: TEXT_LAYER_MODE,
});
this.pdfViewer = pdfViewer;
this.eventBus.on("pagesinit", () => {
// We can use pdfViewer now, e.g. let's change default scale.
pdfViewer.currentScaleValue = "page-actual";
});
}
/**
* Add event handler to PDFViewer's eventbus
*
* @param {*} name PDFViewer event name
* @param {*} fn (event) => {}
*/
on(name, fn) {
this.eventBus.on(name, fn);
}
/**
* Opens PDF document specified by URL.
*/
async open(params) {
console.log("open");
if (this.pdfLoadingTask) {
// We need to destroy already opened document
await this.close()
}
let self = this;
const url = params.url;
this.setTitleUsingUrl(url);
// Loading document
const loadingTask = pdfjsLib.getDocument({
url,
cMapUrl: CMAP_URL,
cMapPacked: CMAP_PACKED,
maxImageSize: MAX_IMAGE_SIZE,
enableXfa: ENABLE_XFA,
});
this.pdfLoadingTask = loadingTask;
let pdfPassword = this.password;
loadingTask.onPassword = (callback, reason) => {
console.log("onPassword: " + reason)
callback(pdfPassword)
}
loadingTask.onProgress = function (progressData) {
self.progress(progressData.loaded / progressData.total);
};
const pdfDocument = await loadingTask.promise
// Document loaded, specifying document for the viewer.
this.pdfDocument = pdfDocument;
console.log("pdfViewer.setDocument")
this.pdfViewer.setDocument(pdfDocument);
self.loadingBar.hide();
this.setTitleUsingMetadata(pdfDocument);
/*
catch((error) => {
const message = error && error.message;
console.log(message);
const l10n = this.l10n;
let loadingErrorMessage;
if (error instanceof pdfjsLib.InvalidPDFException) {
// change error message also for other builds
loadingErrorMessage = l10n.get(
"invalid_file_error",
null,
"Invalid or corrupted PDF file."
);
} else if (error instanceof pdfjsLib.MissingPDFException) {
// special message for missing PDFs
loadingErrorMessage = l10n.get(
"missing_file_error",
null,
"Missing PDF file."
);
} else if (error instanceof pdfjsLib.UnexpectedResponseException) {
loadingErrorMessage = l10n.get(
"unexpected_response_error",
null,
"Unexpected server response."
);
} else {
loadingErrorMessage = l10n.get(
"loading_error",
null,
"An error occurred while loading the PDF."
);
}
loadingErrorMessage.then((msg) => {
console.log(msg);
error.moreInfo = msg;
throw (error);
});
self.loadingBar.hide();
})
*/
}
/**
* Closes opened PDF document
* @returns {Promise} - Returns the promise, which is resolved when all
* destruction is completed.
*/
async close() {
console.log("close");
if (!this.pdfLoadingTask) {
return;
}
await this.pdfLoadingTask.destroy();
this.pdfLoadingTask = null;
if (this.pdfDocument) {
this.pdfDocument = null;
this.pdfViewer.setDocument(null);
}
}
get loadingBar() {
const bar = new pdfjsViewer.ProgressBar("loadingBar");
return pdfjsLib.shadow(this, "loadingBar", bar);
}
progress(level) {
const percent = Math.round(level * 100);
// Updating the bar if value increases.
if (percent > this.loadingBar.percent || isNaN(percent)) {
this.loadingBar.percent = percent;
}
}
setTitle(title) {
document.title = title;
}
setTitleUsingUrl (url) {
this.url = url;
let title = pdfjsLib.getFilenameFromUrl(url) || url;
try {
title = decodeURIComponent(title);
} catch (e) {
// decodeURIComponent may throw URIError,
// fall back to using the unprocessed url in that case
}
this.setTitle(title);
}
setTitleUsingMetadata(pdfDocument) {
const self = this;
pdfDocument.getMetadata()
.then((data) => {
const info = data.info;
const metadata = data.metadata;
self.documentInfo = info;
self.metadata = metadata;
// Provides some basic debug information
console.log(
"PDF " +
pdfDocument.fingerprints[0] +
" [" +
info.PDFFormatVersion +
" " +
(info.Producer || "-").trim() +
" / " +
(info.Creator || "-").trim() +
"]" +
" (PDF.js: " +
(pdfjsLib.version || "-") +
")"
);
let pdfTitle;
if (metadata && metadata.has("dc:title")) {
const title = metadata.get("dc:title");
// Ghostscript sometimes returns 'Untitled', so prevent setting the
// title to 'Untitled.
if (title !== "Untitled") {
pdfTitle = title;
}
}
if (!pdfTitle && info && info.Title) {
pdfTitle = info.Title;
}
if (pdfTitle) {
self.setTitle(pdfTitle + " - " + document.title);
}
});
}
};
export { PDFViewerApp };