flatten (#1167)
This commit is contained in:
parent
d6b1fec69d
commit
ac5273244c
33 changed files with 145 additions and 38 deletions
|
@ -13,8 +13,6 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
@ -76,6 +74,7 @@ public class ConfigInitializer
|
|||
Files.createFile(customSettingsPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> extractEntries(List<String> lines) {
|
||||
Map<String, String> entries = new HashMap<>();
|
||||
StringBuilder currentEntry = new StringBuilder();
|
||||
|
@ -121,8 +120,10 @@ public class ConfigInitializer
|
|||
return entries;
|
||||
}
|
||||
|
||||
|
||||
private static List<String> mergeConfigs(List<String> templateLines, Map<String, String> templateEntries, Map<String, String> userEntries) {
|
||||
private static List<String> mergeConfigs(
|
||||
List<String> templateLines,
|
||||
Map<String, String> templateEntries,
|
||||
Map<String, String> userEntries) {
|
||||
List<String> mergedLines = new ArrayList<>();
|
||||
Set<String> handledKeys = new HashSet<>();
|
||||
|
||||
|
@ -141,7 +142,8 @@ public class ConfigInitializer
|
|||
blockIndent = indentLevel;
|
||||
}
|
||||
|
||||
if (userEntries.containsKey(currentBlockKey) && !handledKeys.contains(currentBlockKey)) {
|
||||
if (userEntries.containsKey(currentBlockKey)
|
||||
&& !handledKeys.contains(currentBlockKey)) {
|
||||
mergedLines.add(userEntries.get(currentBlockKey));
|
||||
handledKeys.add(currentBlockKey);
|
||||
} else if (!handledKeys.contains(currentBlockKey)) {
|
||||
|
@ -152,8 +154,6 @@ public class ConfigInitializer
|
|||
return mergedLines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static List<String> cleanInvalidYamlEntries(List<String> lines) {
|
||||
List<String> cleanedLines = new ArrayList<>();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
|
|
|
@ -85,6 +85,7 @@ public class InitialSecuritySetup {
|
|||
// Write back to the file
|
||||
Files.write(path, lines);
|
||||
}
|
||||
|
||||
private boolean isValidUUID(String uuid) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
|
@ -96,5 +97,4 @@ public class InitialSecuritySetup {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package stirling.software.SPDF.controller.api.misc;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import stirling.software.SPDF.model.PdfMetadata;
|
||||
import stirling.software.SPDF.model.api.misc.FlattenRequest;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/misc")
|
||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||
public class FlattenController {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
|
||||
@Operation(
|
||||
summary = "Flatten PDF form fields or full page",
|
||||
description =
|
||||
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
|
||||
public ResponseEntity<byte[]> flatten(@ModelAttribute FlattenRequest request) throws Exception {
|
||||
MultipartFile file = request.getFileInput();
|
||||
|
||||
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||
PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
|
||||
Boolean flattenOnlyForms = request.getFlattenOnlyForms();
|
||||
|
||||
if (Boolean.TRUE.equals(flattenOnlyForms)) {
|
||||
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
|
||||
if (acroForm != null) {
|
||||
acroForm.flatten();
|
||||
}
|
||||
return WebResponseUtils.pdfDocToWebResponse(
|
||||
document, Filenames.toSimpleFileName(file.getOriginalFilename()));
|
||||
} else {
|
||||
// flatten whole page aka convert each page to image and readd it (making text
|
||||
// unselectable)
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
PDDocument newDocument = new PDDocument();
|
||||
int numPages = document.getNumberOfPages();
|
||||
for (int i = 0; i < numPages; i++) {
|
||||
try {
|
||||
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);
|
||||
PDPage page = new PDPage();
|
||||
page.setMediaBox(document.getPage(i).getMediaBox());
|
||||
newDocument.addPage(page);
|
||||
try (PDPageContentStream contentStream =
|
||||
new PDPageContentStream(newDocument, page)) {
|
||||
PDImageXObject pdImage = JPEGFactory.createFromImage(newDocument, image);
|
||||
float pageWidth = page.getMediaBox().getWidth();
|
||||
float pageHeight = page.getMediaBox().getHeight();
|
||||
|
||||
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
PdfUtils.setMetadataToPdf(newDocument, metadata);
|
||||
return WebResponseUtils.pdfDocToWebResponse(
|
||||
newDocument, Filenames.toSimpleFileName(file.getOriginalFilename()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package stirling.software.SPDF.model.api.misc;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import stirling.software.SPDF.model.api.PDFFile;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class FlattenRequest extends PDFFile {
|
||||
|
||||
@Schema(
|
||||
description =
|
||||
"True to flatten only the forms, false to flatten full PDF (Convert page to image)")
|
||||
private Boolean flattenOnlyForms;
|
||||
}
|
|
@ -694,6 +694,7 @@ repair.submit=الإصلاح
|
|||
#flatten
|
||||
flatten.title=تسطيح
|
||||
flatten.header=تسوية ملفات PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=تسطيح
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Поправи
|
|||
#flatten
|
||||
flatten.title=Изравнете
|
||||
flatten.header=Изравнете PDF-и
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Изравнете
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparar
|
|||
#flatten
|
||||
flatten.title=Aplanar
|
||||
flatten.header=Aplana els PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Aplanar
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparieren
|
|||
#flatten
|
||||
flatten.title=Abflachen
|
||||
flatten.header=PDFs reduzieren
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Abflachen
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Επιδιόρθωση
|
|||
#flatten
|
||||
flatten.title=Flatten
|
||||
flatten.header=Flatten PDFs
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Flatten
|
||||
|
||||
|
||||
|
|
|
@ -693,7 +693,8 @@ repair.submit=Repair
|
|||
|
||||
#flatten
|
||||
flatten.title=Flatten
|
||||
flatten.header=Flatten PDFs
|
||||
flatten.header=Flatten PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Flatten
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Repair
|
|||
#flatten
|
||||
flatten.title=Flatten
|
||||
flatten.header=Flatten PDFs
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Flatten
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparar
|
|||
#flatten
|
||||
flatten.title=Aplanar
|
||||
flatten.header=Acoplar archivos PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Aplanar
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Konpondu
|
|||
#flatten
|
||||
flatten.title=Lautu
|
||||
flatten.header=Akoplatu PDF fitxategiak
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Lautu
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Réparer
|
|||
#flatten
|
||||
flatten.title=Rendre inerte
|
||||
flatten.header=Rendre inerte
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Rendre inerte
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=मरम्मत
|
|||
#flatten
|
||||
flatten.title=समतल करें
|
||||
flatten.header=पीडीएफ़ समतल करें
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=समतल करें
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Javítás
|
|||
#flatten
|
||||
flatten.title=Kiegyenlítés
|
||||
flatten.header=PDF-ek kiegyenlítése
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Kiegyenlítés
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Perbaiki
|
|||
#flatten
|
||||
flatten.title=Ratakan
|
||||
flatten.header=Ratakan PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Ratakan
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Ripara
|
|||
#flatten
|
||||
flatten.title=Appiattisci
|
||||
flatten.header=Appiattisci PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Appiattisci
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=修復
|
|||
#flatten
|
||||
flatten.title=平坦化
|
||||
flatten.header=PDFを平坦化する
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=平坦化
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=복구
|
|||
#flatten
|
||||
flatten.title=평탄화
|
||||
flatten.header=PDF 문서의 레이어 평탄화
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=평탄화
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Repareren
|
|||
#flatten
|
||||
flatten.title=Afvlakken
|
||||
flatten.header=PDF's afvlakken
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Afvlakken
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Napraw
|
|||
#flatten
|
||||
flatten.title=Spłaszcz
|
||||
flatten.header=Spłaszcz dokument(y) PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Spłaszcz
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparar
|
|||
#flatten
|
||||
flatten.title=Achatar
|
||||
flatten.header=Achatar PDFs
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Achatar
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparar
|
|||
#flatten
|
||||
flatten.title=Achatar
|
||||
flatten.header=Achatar PDFs
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Achatar
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Repară
|
|||
#flatten
|
||||
flatten.title=Nivelare
|
||||
flatten.header=Nivelează documente PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Nivelează
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Ремонт
|
|||
#flatten
|
||||
flatten.title=Сглаживание
|
||||
flatten.header=Сглаживание PDF ов
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Сгладить
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Popravi
|
|||
#flatten
|
||||
flatten.title=Ravnanje
|
||||
flatten.header=Ravnanje PDF fajlova
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Ravnanje
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Reparera
|
|||
#flatten
|
||||
flatten.title=Platta till
|
||||
flatten.header=Placera PDF-filer
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Platta till
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Onar
|
|||
#flatten
|
||||
flatten.title=Düzleştir
|
||||
flatten.header=PDF'leri Düzleştir
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Düzleştir
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=Ремонтувати
|
|||
#flatten
|
||||
flatten.title=Згладжування
|
||||
flatten.header=Згладжування PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Згладити
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=修复
|
|||
#flatten
|
||||
flatten.title=展平
|
||||
flatten.header=展平 PDF
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=展平
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ repair.submit=修復
|
|||
#flatten
|
||||
flatten.title=平坦化
|
||||
flatten.header=PDF 平坦化
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=平坦化
|
||||
|
||||
|
||||
|
|
|
@ -13,36 +13,14 @@
|
|||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 th:text="#{flatten.header}"></h2>
|
||||
<form id="pdfForm" class="mb-3">
|
||||
<div class="custom-file">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/misc/flatten}">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||
<div class="mb-3-inline form-check">
|
||||
<input type="checkbox" class="form-check-input" id="flattenOnlyForms" name="flattenOnlyForms">
|
||||
<label class="ms-3" for="flattenOnlyForms" th:text="#{flatten.flattenOnlyForms}" ></label>
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{flatten.submit}"></button>
|
||||
<script src="js/local-pdf-input-download.js"></script>
|
||||
<script>
|
||||
document.getElementById('pdfForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const { PDFDocument } = PDFLib;
|
||||
|
||||
const processFile = async (file) => {
|
||||
const origFileUrl = URL.createObjectURL(file);
|
||||
const formPdfBytes = await fetch(origFileUrl).then(res => res.arrayBuffer());
|
||||
const pdfDoc = await PDFDocument.load(formPdfBytes, { ignoreEncryption: true });
|
||||
|
||||
const form = pdfDoc.getForm();
|
||||
form.flatten();
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const fileName = (file.name ? file.name.replace('.pdf', '') : 'pdf') + '_flattened.pdf';
|
||||
|
||||
return { processedData: pdfBlob, fileName };
|
||||
};
|
||||
|
||||
await downloadFilesWithCallback(processFile);
|
||||
});
|
||||
</script>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue