duplex
This commit is contained in:
parent
8a2aa44de8
commit
8bbbdbd359
3 changed files with 157 additions and 11 deletions
|
@ -1,6 +1,7 @@
|
||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -79,26 +80,148 @@ public class RearrangePagesPDFController {
|
||||||
return newPageOrder;
|
return newPageOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum CustomMode {
|
||||||
|
REVERSE_ORDER,
|
||||||
|
DUPLEX_SORT,
|
||||||
|
BOOKLET_SORT,
|
||||||
|
ODD_EVEN_SPLIT,
|
||||||
|
REMOVE_FIRST,
|
||||||
|
REMOVE_LAST,
|
||||||
|
REMOVE_FIRST_AND_LAST,
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> removeFirst(int totalPages) {
|
||||||
|
if (totalPages <= 1) return new ArrayList<>();
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = 2; i <= totalPages; i++) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> removeLast(int totalPages) {
|
||||||
|
if (totalPages <= 1) return new ArrayList<>();
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = 1; i < totalPages; i++) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> removeFirstAndLast(int totalPages) {
|
||||||
|
if (totalPages <= 2) return new ArrayList<>();
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = 2; i < totalPages; i++) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Integer> reverseOrder(int totalPages) {
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = totalPages; i >= 1; i--) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> duplexSort(int totalPages) {
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
int half = (totalPages + 1) / 2; // This ensures proper behavior with odd numbers of pages
|
||||||
|
for (int i = 1; i <= half; i++) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
if (i <= totalPages - half) { // Avoid going out of bounds
|
||||||
|
newPageOrder.add(totalPages - i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Integer> bookletSort(int totalPages) {
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = 0; i < totalPages / 2; i++) {
|
||||||
|
newPageOrder.add(i);
|
||||||
|
newPageOrder.add(totalPages - i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> oddEvenSplit(int totalPages) {
|
||||||
|
List<Integer> newPageOrder = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= totalPages; i += 2) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
for (int i = 2; i <= totalPages; i += 2) {
|
||||||
|
newPageOrder.add(i - 1);
|
||||||
|
}
|
||||||
|
return newPageOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> processCustomMode(String customMode, int totalPages) {
|
||||||
|
try {
|
||||||
|
CustomMode mode = CustomMode.valueOf(customMode.toUpperCase());
|
||||||
|
switch (mode) {
|
||||||
|
case REVERSE_ORDER:
|
||||||
|
return reverseOrder(totalPages);
|
||||||
|
case DUPLEX_SORT:
|
||||||
|
return duplexSort(totalPages);
|
||||||
|
case BOOKLET_SORT:
|
||||||
|
return bookletSort(totalPages);
|
||||||
|
case ODD_EVEN_SPLIT:
|
||||||
|
return oddEvenSplit(totalPages);
|
||||||
|
case REMOVE_FIRST:
|
||||||
|
return removeFirst(totalPages);
|
||||||
|
case REMOVE_LAST:
|
||||||
|
return removeLast(totalPages);
|
||||||
|
case REMOVE_FIRST_AND_LAST:
|
||||||
|
return removeFirstAndLast(totalPages);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported custom mode");
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.error("Unsupported custom mode", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
|
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
|
||||||
@Operation(summary = "Rearrange pages in a PDF file",
|
@Operation(summary = "Rearrange pages in a PDF file",
|
||||||
description = "This endpoint rearranges pages in a given PDF file based on the specified page order. Users can provide a page order as a comma-separated list of page numbers or page ranges.")
|
description = "This endpoint rearranges pages in a given PDF file based on the specified page order or custom mode. Users can provide a page order as a comma-separated list of page numbers or page ranges, or a custom mode.")
|
||||||
public ResponseEntity<byte[]> rearrangePages(
|
public ResponseEntity<byte[]> rearrangePages(
|
||||||
@RequestPart(required = true, value = "fileInput")
|
@RequestPart(required = true, value = "fileInput")
|
||||||
@Parameter(description = "The input PDF file to rearrange pages")
|
@Parameter(description = "The input PDF file to rearrange pages")
|
||||||
MultipartFile pdfFile,
|
MultipartFile pdfFile,
|
||||||
@RequestParam("pageOrder")
|
@RequestParam(required = false, value = "pageOrder")
|
||||||
@Parameter(description = "The new page order as a comma-separated list of page numbers or page ranges (e.g., '1,3,5-7')")
|
@Parameter(description = "The new page order as a comma-separated list of page numbers or page ranges (e.g., '1,3,5-7')")
|
||||||
String pageOrder) {
|
String pageOrder,
|
||||||
|
@RequestParam(required = false, value = "customMode")
|
||||||
|
@Parameter(schema = @Schema(implementation = CustomMode.class, description = "The custom mode for page rearrangement. " +
|
||||||
|
"Valid values are:\n" +
|
||||||
|
"REVERSE_ORDER: Reverses the order of all pages.\n" +
|
||||||
|
"DUPLEX_SORT: Sorts pages as if all fronts were scanned then all backs in reverse (1, n, 2, n-1, ...). " +
|
||||||
|
"BOOKLET_SORT: Arranges pages for booklet printing (last, first, second, second last, ...).\n" +
|
||||||
|
"ODD_EVEN_SPLIT: Splits and arranges pages into odd and even numbered pages.\n" +
|
||||||
|
"REMOVE_FIRST: Removes the first page.\n" +
|
||||||
|
"REMOVE_LAST: Removes the last page.\n" +
|
||||||
|
"REMOVE_FIRST_AND_LAST: Removes both the first and the last pages.\n"))
|
||||||
|
String customMode) {
|
||||||
try {
|
try {
|
||||||
// Load the input PDF
|
// Load the input PDF
|
||||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||||
|
|
||||||
// Split the page order string into an array of page numbers or range of numbers
|
// Split the page order string into an array of page numbers or range of numbers
|
||||||
String[] pageOrderArr = pageOrder.split(",");
|
String[] pageOrderArr = pageOrder != null ? pageOrder.split(",") : new String[0];
|
||||||
// int[] newPageOrder = new int[pageOrderArr.length];
|
|
||||||
int totalPages = document.getNumberOfPages();
|
int totalPages = document.getNumberOfPages();
|
||||||
|
System.out.println("pageOrder=" + pageOrder);
|
||||||
List<Integer> newPageOrder = pageOrderToString(pageOrderArr, totalPages);
|
System.out.println("customMode length =" + customMode.length());
|
||||||
|
List<Integer> newPageOrder;
|
||||||
|
if(customMode != null && customMode.length() > 0) {
|
||||||
|
newPageOrder = processCustomMode(customMode, totalPages);
|
||||||
|
} else {
|
||||||
|
newPageOrder = pageOrderToString(pageOrderArr, totalPages);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new list to hold the pages in the new order
|
// Create a new list to hold the pages in the new order
|
||||||
List<PDPage> newPages = new ArrayList<>();
|
List<PDPage> newPages = new ArrayList<>();
|
||||||
|
@ -118,10 +241,10 @@ public class RearrangePagesPDFController {
|
||||||
|
|
||||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rearranged.pdf");
|
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_rearranged.pdf");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
||||||
logger.error("Failed rearranging documents", e);
|
logger.error("Failed rearranging documents", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ multiPdfDropPrompt=Select (or drag & drop) all PDFs you require
|
||||||
imgPrompt=Select Image(s)
|
imgPrompt=Select Image(s)
|
||||||
genericSubmit=Submit
|
genericSubmit=Submit
|
||||||
processTimeWarning=Warning: This process can take up to a minute depending on file-size
|
processTimeWarning=Warning: This process can take up to a minute depending on file-size
|
||||||
pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) :
|
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers) :
|
||||||
goToPage=Go
|
goToPage=Go
|
||||||
true=True
|
true=True
|
||||||
false=False
|
false=False
|
||||||
|
|
|
@ -17,12 +17,35 @@
|
||||||
<form th:action="@{rearrange-pages}" method="post" enctype="multipart/form-data">
|
<form th:action="@{rearrange-pages}" method="post" enctype="multipart/form-data">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pageOrder" th:text="#{pageOrderPrompt}"></label>
|
<label for="customMode">Mode</label>
|
||||||
<input type="text" class="form-control" id="fileInput" name="pageOrder" placeholder="(e.g. 1,3,2 or 4-8,2,10-12)" required>
|
<select class="form-control" id="customMode" name="customMode">
|
||||||
|
<option value="">Custom Page Order</option>
|
||||||
|
<option value="REVERSE_ORDER">Reverse Order</option>
|
||||||
|
<option value="DUPLEX_SORT">Duplex Sort</option>
|
||||||
|
<option value="BOOKLET_SORT">Booklet Sort</option>
|
||||||
|
<option value="ODD_EVEN_SPLIT">Odd-Even Split</option>
|
||||||
|
<option value="REMOVE_FIRST">Remove First</option>
|
||||||
|
<option value="REMOVE_LAST">Remove Last</option>
|
||||||
|
<option value="REMOVE_FIRST_AND_LAST">Remove First and Last</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="pageOrder" th:text="#{pageOrderPrompt}"></label>
|
||||||
|
<input type="text" class="form-control" id="pageOrder" name="pageOrder" placeholder="(e.g. 1,3,2 or 4-8,2,10-12)" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfOrganiser.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfOrganiser.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
|
<script>
|
||||||
|
document.getElementById('customMode').addEventListener('change', function () {
|
||||||
|
var pageOrderInput = document.getElementById('pageOrder');
|
||||||
|
if (this.value === "") {
|
||||||
|
pageOrderInput.disabled = false;
|
||||||
|
} else {
|
||||||
|
pageOrderInput.disabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue