I am trying to create an HTML web page that can convert a PDF file to JPG images and then export the rearranged pages as a new PDF file.
The codes are shown as follows:
<!DOCTYPE html>
<html>
<head>
<title>PDF pages rearranger</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script>
<style>
/* Define the style for the container element */
#container {
width: 600px;
height: 400px;
border: 1px solid black;
margin: 20px auto;
overflow: auto;
}
/* Define the style for the image elements */
img {
width: 100px;
height: 100px;
margin: 10px;
cursor: move; /* Change the cursor to indicate that the images are draggable */
}
</style>
<!-- Load the jQuery library from a CDN -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Load the jQuery UI library from a CDN -->
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js"></script>
<!-- Load the jsPDF library from a CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
</head>
<body>
<input type="file" id="fileInput" accept=".pdf" />
<button id="convertButton">Convert to JPG</button>
<!-- Create a div element to hold the images -->
<div id="container"></div>
<!-- Create a button to export the rearranged pages as a new PDF file -->
<button id="exportButton">Export as PDF</button>
<script>
// Set the GlobalWorkerOptions.workerSrc property
window.GlobalWorkerOptions = {
workerSrc: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.worker.min.js'
};
const fileInput = document.getElementById('fileInput');
const convertButton = document.getElementById('convertButton');
const container = document.getElementById('container');
const exportButton = document.getElementById('exportButton');
convertButton.addEventListener('click', async () => {
const file = fileInput.files[0];
if (!file) {
alert('Please select a PDF file first');
return;
}
// Clear any existing images in the container
container.innerHTML = '';
const reader = new FileReader();
reader.onload = async (event) => {
const typedArray = new Uint8Array(event.target.result);
const pdfDocument = await pdfjsLib.getDocument(typedArray).promise;
const numPages = pdfDocument.numPages;
for (let i = 1; i <= numPages; i++) {
const page = await pdfDocument.getPage(i);
const viewport = page.getViewport({ scale: 1.0 });
const canvas = document.createElement('canvas');
canvas.width = viewport.width;
canvas.height = viewport.height;
const ctx = canvas.getContext('2d');
await page.render({ canvasContext: ctx, viewport }).promise;
const dataUrl = canvas.toDataURL('image/jpeg');
download(dataUrl, `page${i}.jpg`);
// Create an img element for each page and add it to the container
const img = document.createElement('img');
img.src = dataUrl;
img.alt = `Page ${i}`;
container.appendChild(img);
}
// Make the image elements draggable and sortable using jQuery UI
$("#container").sortable({
// Define a helper function to create a clone of the dragged image
helper: function(e, ui) {
return $(ui).clone().appendTo("#container").show();
}
});
};
reader.readAsArrayBuffer(file);
});
exportButton.addEventListener('click', () => {
// Create a new jsPDF instance
const doc = new jsPDF();
// Get all the img elements in the container
const images = container.querySelectorAll('img');
// Add each image to the PDF document
images.forEach((img, index) => {
if (index > 0) {
doc.addPage();
}
doc.addImage(img.src, 'JPEG', 10, 10);
});
// Save the PDF document
doc.save('rearranged.pdf');
});
function download(dataUrl, filename) {
const link = document.createElement('a');
link.href = dataUrl;
link.download = filename;
link.click();
}
</script>
</body>
</html>
However, when I tried to run the code, I encountered two issues:
The first warning message appears when I click the "Convert to JPG" button, saying “Deprecated API usage: No GlobalWorkerOptions.workerSrc specified.” I guess it is caused by the fact that the GlobalWorkerOptions.workerSrc property is not being set correctly.
The second warning message appears when I click the "Export as PDF" button, saying “Uncaught ReferenceError: jsPDF is not defined.” So seems the jsPDF library is not being loaded correctly.
Can anyone help me understand what might be causing these issues and provide suggestions for how to resolve them?
Edit:
With the help of @Alirahmon Nuraliev, my first problem is solved, but the second problem still remains unsolved, which is “Uncaught ReferenceError: jsPDF is not defined.”.
My rectified codes is as follows:
<!DOCTYPE html>
<html>
<head>
<title>PDF pages rearranger</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script>
<style>
/* Define the style for the container element */
#container {
width: 600px;
height: 400px;
border: 1px solid black;
margin: 20px auto;
overflow: auto;
}
/* Define the style for the image elements */
img {
width: 100px;
height: 100px;
margin: 10px;
cursor: move; /* Change the cursor to indicate that the images are draggable */
}
</style>
<!-- Load the jQuery library from a CDN -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Load the jQuery UI library from a CDN -->
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js"></script>
</head>
<body>
<input type="file" id="fileInput" accept=".pdf" />
<button id="convertButton">Convert to JPG</button>
<!-- Create a div element to hold the images -->
<div id="container"></div>
<!-- Create a button to export the rearranged pages as a new PDF file -->
<button id="exportButton">Export as PDF</button>
<script>
// Set the GlobalWorkerOptions.workerSrc property
const workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.worker.min.js';
const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
const fileInput = document.getElementById('fileInput');
const convertButton = document.getElementById('convertButton');
const container = document.getElementById('container');
const exportButton = document.getElementById('exportButton');
convertButton.addEventListener('click', async () => {
const file = fileInput.files[0];
if (!file) {
alert('Please select a PDF file first');
return;
}
// Clear any existing images in the container
container.innerHTML = '';
const reader = new FileReader();
reader.onload = async (event) => {
const typedArray = new Uint8Array(event.target.result);
const pdfDocument = await pdfjsLib.getDocument(typedArray).promise;
const numPages = pdfDocument.numPages;
for (let i = 1; i <= numPages; i++) {
const page = await pdfDocument.getPage(i);
const viewport = page.getViewport({ scale: 1.0 });
const canvas = document.createElement('canvas');
canvas.width = viewport.width;
canvas.height = viewport.height;
const ctx = canvas.getContext('2d');
await page.render({ canvasContext: ctx, viewport }).promise;
const dataUrl = canvas.toDataURL('image/jpeg');
download(dataUrl, `page${i}.jpg`);
// Create an img element for each page and add it to the container
const img = document.createElement('img');
img.src = dataUrl;
img.alt = `Page ${i}`;
container.appendChild(img);
}
// Make the image elements draggable and sortable using jQuery UI
$("#container").sortable({
// Define a helper function to create a clone of the dragged image
helper: function(e, ui) {
return $(ui).clone().appendTo("#container").show();
}
});
};
reader.readAsArrayBuffer(file);
});
// Load jsPDF library and add event listener for export button
const jsPDFScript = document.createElement('script');
jsPDFScript.src =
'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
jsPDFScript.onload = () => {
exportButton.addEventListener('click', () => {
// Create a new jsPDF instance
const doc = new jsPDF();
// Get all the img elements in the container
const images = container.querySelectorAll('img');
// Add each image to the PDF document
images.forEach((img, index) => {
if (index > 0) {
doc.addPage();
}
doc.addImage(img.src, 'JPEG', 10, 10);
});
// Save the PDF document
doc.save('rearranged.pdf');
});
};
document.body.appendChild(jsPDFScript);
function download(dataUrl, filename) {
const link = document.createElement('a');
link.href = dataUrl;
link.download = filename;
link.click();
}
</script>
</body>
</html>
2
Answers
The issues you’re facing are indeed related to the order of loading and potential timing issues with external libraries. Let’s address each issue separately:
Deprecated API usage warning (GlobalWorkerOptions.workerSrc):
To fix the "Deprecated API usage" warning, you need to set the
GlobalWorkerOptions.workerSrc
property after thepdf.js
library has been loaded. You can achieve this by using theworkerSrc
option when initializing thepdfjsLib
object. Place the following code at the beginning of your script:Then, you can continue with the rest of your script as before.
Uncaught ReferenceError: jsPDF is not defined:
This error occurs because the
jsPDF
library is not being loaded or recognized. You need to ensure that thejsPDF
library is fully loaded before you use it.To solve this issue, you can include your export code within an event listener for the
jsPDF
script’sload
event. Here’s how you can do it:Place this script after the section where you define the
exportButton
and the other elements.By addressing these two issues, your code should work as expected without warnings and errors. The key is to ensure that the required libraries are loaded and initialized in the correct order.
Try this code