mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-08-11 13:48:37 +02:00
Merge to generate ToC
This commit is contained in:
parent
704b8bb0c6
commit
cab1fa9297
@ -15,6 +15,8 @@ import org.apache.pdfbox.multipdf.PDFMergerUtility;
|
|||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||||
@ -124,6 +126,7 @@ public class MergeController {
|
|||||||
PDDocument mergedDocument = null;
|
PDDocument mergedDocument = null;
|
||||||
|
|
||||||
boolean removeCertSign = form.isRemoveCertSign();
|
boolean removeCertSign = form.isRemoveCertSign();
|
||||||
|
boolean generateToc = form.isGenerateToc();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MultipartFile[] files = form.getFileInput();
|
MultipartFile[] files = form.getFileInput();
|
||||||
@ -170,6 +173,11 @@ public class MergeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate table of contents if requested
|
||||||
|
if (generateToc) {
|
||||||
|
generateTableOfContents(mergedDocument, files);
|
||||||
|
}
|
||||||
|
|
||||||
// Save the modified document to a new ByteArrayOutputStream
|
// Save the modified document to a new ByteArrayOutputStream
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
mergedDocument.save(baos);
|
mergedDocument.save(baos);
|
||||||
@ -197,4 +205,54 @@ public class MergeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a table of contents for the merged PDF document using file names as chapter titles
|
||||||
|
*
|
||||||
|
* @param mergedDocument The merged PDF document
|
||||||
|
* @param files The original input files that were merged
|
||||||
|
*/
|
||||||
|
private void generateTableOfContents(PDDocument mergedDocument, MultipartFile[] files) {
|
||||||
|
PDDocumentCatalog catalog = mergedDocument.getDocumentCatalog();
|
||||||
|
PDDocumentOutline outline = new PDDocumentOutline();
|
||||||
|
catalog.setDocumentOutline(outline);
|
||||||
|
|
||||||
|
int currentPageIndex = 0;
|
||||||
|
|
||||||
|
for (MultipartFile file : files) {
|
||||||
|
try {
|
||||||
|
// Create a temporary file to load document and get page count
|
||||||
|
File tempFile = GeneralUtils.convertMultipartFileToFile(file);
|
||||||
|
PDDocument doc = pdfDocumentFactory.load(tempFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create an outline item for this file
|
||||||
|
String fileName = file.getOriginalFilename();
|
||||||
|
if (fileName != null && fileName.toLowerCase().endsWith(".pdf")) {
|
||||||
|
fileName = fileName.substring(0, fileName.length() - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
PDOutlineItem bookmark = new PDOutlineItem();
|
||||||
|
bookmark.setTitle(fileName);
|
||||||
|
|
||||||
|
// Set destination to the first page of this file in the merged document
|
||||||
|
PDPage page = mergedDocument.getPage(currentPageIndex);
|
||||||
|
bookmark.setDestination(page);
|
||||||
|
|
||||||
|
// Add the bookmark to the outline
|
||||||
|
outline.addLast(bookmark);
|
||||||
|
|
||||||
|
// Update current page index for next file
|
||||||
|
currentPageIndex += doc.getNumberOfPages();
|
||||||
|
} finally {
|
||||||
|
doc.close();
|
||||||
|
Files.deleteIfExists(tempFile.toPath());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error creating bookmark for file: " + file.getOriginalFilename(), e);
|
||||||
|
// Continue with next file even if one fails
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,10 @@ public class MergePdfsRequest extends MultiplePDFFiles {
|
|||||||
"Flag indicating whether to remove certification signatures from the merged PDF. If true, all certification signatures will be removed from the final merged document.",
|
"Flag indicating whether to remove certification signatures from the merged PDF. If true, all certification signatures will be removed from the final merged document.",
|
||||||
example = "true")
|
example = "true")
|
||||||
private boolean isRemoveCertSign;
|
private boolean isRemoveCertSign;
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description =
|
||||||
|
"Flag indicating whether to generate a table of contents for the merged PDF. If true, a table of contents will be created using the input filenames as chapter names.",
|
||||||
|
example = "true")
|
||||||
|
private boolean generateToc = false;
|
||||||
}
|
}
|
||||||
|
@ -1013,6 +1013,7 @@ merge.header=Merge multiple PDFs (2+)
|
|||||||
merge.sortByName=Sort by name
|
merge.sortByName=Sort by name
|
||||||
merge.sortByDate=Sort by date
|
merge.sortByDate=Sort by date
|
||||||
merge.removeCertSign=Remove digital signature in the merged file?
|
merge.removeCertSign=Remove digital signature in the merged file?
|
||||||
|
merge.generateToc=Generate table of contents in the merged file?
|
||||||
merge.submit=Merge
|
merge.submit=Merge
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
<label for="removeCertSign" th:text="#{merge.removeCertSign}">Remove digital signature in the merged
|
<label for="removeCertSign" th:text="#{merge.removeCertSign}">Remove digital signature in the merged
|
||||||
file?</label>
|
file?</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="checkbox" name="generateToc" id="generateToc">
|
||||||
|
<label for="generateToc" th:text="#{merge.generateToc}">Generate table of contents in the merged file?</label>
|
||||||
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<ul id="selectedFiles" class="list-group"></ul>
|
<ul id="selectedFiles" class="list-group"></ul>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user