mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-03 17:52:30 +02:00
feat: implement backend support for selective page splitting in Split PDF by Sections
This commit is contained in:
parent
07b3bfa1f3
commit
1fc40f16c2
@ -5,7 +5,9 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
|
|
||||||
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
|
import stirling.software.common.util.GeneralUtils;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -55,13 +58,20 @@ public class SplitPdfBySectionsController {
|
|||||||
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
||||||
|
|
||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
|
String pageNumbers = request.getPageNumbers();
|
||||||
PDDocument sourceDocument = pdfDocumentFactory.load(file);
|
PDDocument sourceDocument = pdfDocumentFactory.load(file);
|
||||||
|
|
||||||
|
// Split the page order string into an array of page numbers or range of numbers
|
||||||
|
String[] pageOrderArr = pageNumbers.split(",");
|
||||||
|
List<Integer> pageListToSplit =
|
||||||
|
GeneralUtils.parsePageList(pageOrderArr, sourceDocument.getNumberOfPages(), false);
|
||||||
|
Set<Integer> pagesToSplit = new HashSet<>(pageListToSplit);
|
||||||
|
|
||||||
// Process the PDF based on split parameters
|
// Process the PDF based on split parameters
|
||||||
int horiz = request.getHorizontalDivisions() + 1;
|
int horiz = request.getHorizontalDivisions() + 1;
|
||||||
int verti = request.getVerticalDivisions() + 1;
|
int verti = request.getVerticalDivisions() + 1;
|
||||||
boolean merge = Boolean.TRUE.equals(request.getMerge());
|
boolean merge = Boolean.TRUE.equals(request.getMerge());
|
||||||
List<PDDocument> splitDocuments = splitPdfPages(sourceDocument, verti, horiz);
|
List<PDDocument> splitDocuments = splitPdfPages(sourceDocument, verti, horiz, pagesToSplit);
|
||||||
|
|
||||||
String filename =
|
String filename =
|
||||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||||
@ -110,51 +120,61 @@ public class SplitPdfBySectionsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<PDDocument> splitPdfPages(
|
public List<PDDocument> splitPdfPages(
|
||||||
PDDocument document, int horizontalDivisions, int verticalDivisions)
|
PDDocument document, int horizontalDivisions, int verticalDivisions, Set<Integer> pagesToSplit)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
List<PDDocument> splitDocuments = new ArrayList<>();
|
List<PDDocument> splitDocuments = new ArrayList<>();
|
||||||
|
|
||||||
|
int pageIndex = 0;
|
||||||
for (PDPage originalPage : document.getPages()) {
|
for (PDPage originalPage : document.getPages()) {
|
||||||
PDRectangle originalMediaBox = originalPage.getMediaBox();
|
// If current page is not to split, add it to the splitDocuments directly.
|
||||||
float width = originalMediaBox.getWidth();
|
if (!pagesToSplit.contains(pageIndex)) {
|
||||||
float height = originalMediaBox.getHeight();
|
PDDocument newDoc = pdfDocumentFactory.createNewDocument();
|
||||||
float subPageWidth = width / horizontalDivisions;
|
newDoc.addPage(originalPage);
|
||||||
float subPageHeight = height / verticalDivisions;
|
splitDocuments.add(newDoc);
|
||||||
|
} else {
|
||||||
|
// Otherwise, split current page.
|
||||||
|
PDRectangle originalMediaBox = originalPage.getMediaBox();
|
||||||
|
float width = originalMediaBox.getWidth();
|
||||||
|
float height = originalMediaBox.getHeight();
|
||||||
|
float subPageWidth = width / horizontalDivisions;
|
||||||
|
float subPageHeight = height / verticalDivisions;
|
||||||
|
|
||||||
LayerUtility layerUtility = new LayerUtility(document);
|
LayerUtility layerUtility = new LayerUtility(document);
|
||||||
|
|
||||||
for (int i = 0; i < horizontalDivisions; i++) {
|
for (int i = 0; i < horizontalDivisions; i++) {
|
||||||
for (int j = 0; j < verticalDivisions; j++) {
|
for (int j = 0; j < verticalDivisions; j++) {
|
||||||
PDDocument subDoc = new PDDocument();
|
PDDocument subDoc = new PDDocument();
|
||||||
PDPage subPage = new PDPage(new PDRectangle(subPageWidth, subPageHeight));
|
PDPage subPage = new PDPage(new PDRectangle(subPageWidth, subPageHeight));
|
||||||
subDoc.addPage(subPage);
|
subDoc.addPage(subPage);
|
||||||
|
|
||||||
PDFormXObject form =
|
PDFormXObject form =
|
||||||
layerUtility.importPageAsForm(
|
layerUtility.importPageAsForm(
|
||||||
document, document.getPages().indexOf(originalPage));
|
document, document.getPages().indexOf(originalPage));
|
||||||
|
|
||||||
try (PDPageContentStream contentStream =
|
try (PDPageContentStream contentStream =
|
||||||
new PDPageContentStream(
|
new PDPageContentStream(
|
||||||
subDoc, subPage, AppendMode.APPEND, true, true)) {
|
subDoc, subPage, AppendMode.APPEND, true, true)) {
|
||||||
// Set clipping area and position
|
// Set clipping area and position
|
||||||
float translateX = -subPageWidth * i;
|
float translateX = -subPageWidth * i;
|
||||||
|
|
||||||
// float translateY = height - subPageHeight * (verticalDivisions - j);
|
// float translateY = height - subPageHeight * (verticalDivisions - j);
|
||||||
float translateY = -subPageHeight * (verticalDivisions - 1 - j);
|
float translateY = -subPageHeight * (verticalDivisions - 1 - j);
|
||||||
|
|
||||||
contentStream.saveGraphicsState();
|
contentStream.saveGraphicsState();
|
||||||
contentStream.addRect(0, 0, subPageWidth, subPageHeight);
|
contentStream.addRect(0, 0, subPageWidth, subPageHeight);
|
||||||
contentStream.clip();
|
contentStream.clip();
|
||||||
contentStream.transform(new Matrix(1, 0, 0, 1, translateX, translateY));
|
contentStream.transform(new Matrix(1, 0, 0, 1, translateX, translateY));
|
||||||
|
|
||||||
// Draw the form
|
// Draw the form
|
||||||
contentStream.drawForm(form);
|
contentStream.drawForm(form);
|
||||||
contentStream.restoreGraphicsState();
|
contentStream.restoreGraphicsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
splitDocuments.add(subDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
splitDocuments.add(subDoc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pageIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return splitDocuments;
|
return splitDocuments;
|
||||||
|
@ -10,6 +10,12 @@ import stirling.software.common.model.api.PDFFile;
|
|||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class SplitPdfBySectionsRequest extends PDFFile {
|
public class SplitPdfBySectionsRequest extends PDFFile {
|
||||||
|
@Schema(
|
||||||
|
description = "Pages to be split by section",
|
||||||
|
defaultValue = "all",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String pageNumbers;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "Number of horizontal divisions for each PDF page",
|
description = "Number of horizontal divisions for each PDF page",
|
||||||
defaultValue = "0",
|
defaultValue = "0",
|
||||||
|
Loading…
Reference in New Issue
Block a user