formatting

This commit is contained in:
Anthony Stirling
2023-12-30 19:11:27 +00:00
parent 7b43fca6fc
commit 5f771b7851
155 changed files with 5539 additions and 4767 deletions

View File

@@ -28,5 +28,4 @@ public class ErrorUtils {
modelAndView.addObject("stackTrace", stackTrace);
return modelAndView;
}
}

View File

@@ -14,82 +14,87 @@ import java.util.zip.ZipInputStream;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class FileToPdf {
public static byte[] convertHtmlToPdf(byte[] fileBytes, String fileName) throws IOException, InterruptedException {
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
Path tempInputFile = null;
byte[] pdfBytes;
try {
if (fileName.endsWith(".html")) {
tempInputFile = Files.createTempFile("input_", ".html");
Files.write(tempInputFile, fileBytes);
} else {
tempInputFile = unzipAndGetMainHtml(fileBytes);
}
List<String> command = new ArrayList<>();
command.add("weasyprint");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
ProcessExecutorResult returnCode;
if (fileName.endsWith(".zip")) {
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command, tempInputFile.getParent().toFile());
} else {
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
}
pdfBytes = Files.readAllBytes(tempOutputFile);
} finally {
// Clean up temporary files
Files.delete(tempOutputFile);
Files.delete(tempInputFile);
if (fileName.endsWith(".zip")) {
GeneralUtils.deleteDirectory(tempInputFile.getParent());
}
}
return pdfBytes;
}
public static byte[] convertHtmlToPdf(byte[] fileBytes, String fileName)
throws IOException, InterruptedException {
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
Path tempDirectory = Files.createTempDirectory("unzipped_");
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(fileBytes))) {
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
Path filePath = tempDirectory.resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectories(filePath); // Explicitly create the directory structure
} else {
Files.createDirectories(filePath.getParent()); // Create parent directories if they don't exist
Files.copy(zipIn, filePath);
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
}
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
Path tempInputFile = null;
byte[] pdfBytes;
try {
if (fileName.endsWith(".html")) {
tempInputFile = Files.createTempFile("input_", ".html");
Files.write(tempInputFile, fileBytes);
} else {
tempInputFile = unzipAndGetMainHtml(fileBytes);
}
//search for the main HTML file.
try (Stream<Path> walk = Files.walk(tempDirectory)) {
List<Path> htmlFiles = walk.filter(file -> file.toString().endsWith(".html"))
.collect(Collectors.toList());
List<String> command = new ArrayList<>();
command.add("weasyprint");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
ProcessExecutorResult returnCode;
if (fileName.endsWith(".zip")) {
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(
command, tempInputFile.getParent().toFile());
} else {
if (htmlFiles.isEmpty()) {
throw new IOException("No HTML files found in the unzipped directory.");
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
}
// Prioritize 'index.html' if it exists, otherwise use the first .html file
for (Path htmlFile : htmlFiles) {
if (htmlFile.getFileName().toString().equals("index.html")) {
return htmlFile;
}
}
pdfBytes = Files.readAllBytes(tempOutputFile);
} finally {
// Clean up temporary files
Files.delete(tempOutputFile);
Files.delete(tempInputFile);
return htmlFiles.get(0);
}
}
if (fileName.endsWith(".zip")) {
GeneralUtils.deleteDirectory(tempInputFile.getParent());
}
}
return pdfBytes;
}
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
Path tempDirectory = Files.createTempDirectory("unzipped_");
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(fileBytes))) {
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
Path filePath = tempDirectory.resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectories(filePath); // Explicitly create the directory structure
} else {
Files.createDirectories(
filePath.getParent()); // Create parent directories if they don't exist
Files.copy(zipIn, filePath);
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
}
// search for the main HTML file.
try (Stream<Path> walk = Files.walk(tempDirectory)) {
List<Path> htmlFiles =
walk.filter(file -> file.toString().endsWith(".html"))
.collect(Collectors.toList());
if (htmlFiles.isEmpty()) {
throw new IOException("No HTML files found in the unzipped directory.");
}
// Prioritize 'index.html' if it exists, otherwise use the first .html file
for (Path htmlFile : htmlFiles) {
if (htmlFile.getFileName().toString().equals("index.html")) {
return htmlFile;
}
}
return htmlFiles.get(0);
}
}
}

View File

@@ -16,46 +16,50 @@ import java.util.ArrayList;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public class GeneralUtils {
public static void deleteDirectory(Path path) throws IOException {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
public static void deleteDirectory(Path path) throws IOException {
Files.walkFileTree(
path,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
public static String convertToFileName(String name) {
public static String convertToFileName(String name) {
String safeName = name.replaceAll("[^a-zA-Z0-9]", "_");
if (safeName.length() > 50) {
safeName = safeName.substring(0, 50);
}
return safeName;
}
public static boolean isValidURL(String urlStr) {
try {
new URL(urlStr);
return true;
} catch (MalformedURLException e) {
return false;
}
}
public static File multipartToFile(MultipartFile multipart) throws IOException {
public static boolean isValidURL(String urlStr) {
try {
new URL(urlStr);
return true;
} catch (MalformedURLException e) {
return false;
}
}
public static File multipartToFile(MultipartFile multipart) throws IOException {
Path tempFile = Files.createTempFile("overlay-", ".pdf");
try (InputStream in = multipart.getInputStream();
FileOutputStream out = new FileOutputStream(tempFile.toFile())) {
try (InputStream in = multipart.getInputStream();
FileOutputStream out = new FileOutputStream(tempFile.toFile())) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
@@ -64,110 +68,119 @@ public class GeneralUtils {
}
return tempFile.toFile();
}
public static Long convertSizeToBytes(String sizeStr) {
if (sizeStr == null) {
return null;
}
sizeStr = sizeStr.trim().toUpperCase();
try {
if (sizeStr.endsWith("KB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
} else if (sizeStr.endsWith("MB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024);
} else if (sizeStr.endsWith("GB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024 * 1024);
} else if (sizeStr.endsWith("B")) {
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
} else {
// Assume MB if no unit is specified
return (long) (Double.parseDouble(sizeStr) * 1024 * 1024);
}
} catch (NumberFormatException e) {
// The numeric part of the input string cannot be parsed, handle this case
}
return null;
}
public static List<Integer> parsePageString(String pageOrder, int totalPages) {
return parsePageList(pageOrder.split(","), totalPages);
}
public static List<Integer> parsePageList(String[] pageOrderArr, int totalPages) {
List<Integer> newPageOrder = new ArrayList<>();
public static Long convertSizeToBytes(String sizeStr) {
if (sizeStr == null) {
return null;
}
// loop through the page order array
for (String element : pageOrderArr) {
if (element.equalsIgnoreCase("all")) {
for (int i = 0; i < totalPages; i++) {
newPageOrder.add(i);
}
// As all pages are already added, no need to check further
break;
}
else if (element.matches("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
// Handle page order as a function
int coefficient = 0;
int constant = 0;
boolean coefficientExists = false;
boolean constantExists = false;
sizeStr = sizeStr.trim().toUpperCase();
try {
if (sizeStr.endsWith("KB")) {
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
} else if (sizeStr.endsWith("MB")) {
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024);
} else if (sizeStr.endsWith("GB")) {
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024
* 1024);
} else if (sizeStr.endsWith("B")) {
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
} else {
// Assume MB if no unit is specified
return (long) (Double.parseDouble(sizeStr) * 1024 * 1024);
}
} catch (NumberFormatException e) {
// The numeric part of the input string cannot be parsed, handle this case
}
if (element.contains("n")) {
String[] parts = element.split("n");
if (!parts[0].equals("") && parts[0] != null) {
coefficient = Integer.parseInt(parts[0]);
coefficientExists = true;
}
if (parts.length > 1 && !parts[1].equals("") && parts[1] != null) {
constant = Integer.parseInt(parts[1]);
constantExists = true;
}
} else if (element.contains("+")) {
constant = Integer.parseInt(element.replace("+", ""));
constantExists = true;
}
return null;
}
for (int i = 1; i <= totalPages; i++) {
int pageNum = coefficientExists ? coefficient * i : i;
pageNum += constantExists ? constant : 0;
public static List<Integer> parsePageString(String pageOrder, int totalPages) {
return parsePageList(pageOrder.split(","), totalPages);
}
if (pageNum <= totalPages && pageNum > 0) {
newPageOrder.add(pageNum - 1);
}
}
} else if (element.contains("-")) {
// split the range into start and end page
String[] range = element.split("-");
int start = Integer.parseInt(range[0]);
int end = Integer.parseInt(range[1]);
// check if the end page is greater than total pages
if (end > totalPages) {
end = totalPages;
}
// loop through the range of pages
for (int j = start; j <= end; j++) {
// print the current index
newPageOrder.add(j - 1);
}
} else {
// if the element is a single page
newPageOrder.add(Integer.parseInt(element) - 1);
}
}
public static List<Integer> parsePageList(String[] pageOrderArr, int totalPages) {
List<Integer> newPageOrder = new ArrayList<>();
return newPageOrder;
}
public static boolean createDir(String path) {
Path folder = Paths.get(path);
if (!Files.exists(folder)) {
try {
Files.createDirectories(folder);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
// loop through the page order array
for (String element : pageOrderArr) {
if (element.equalsIgnoreCase("all")) {
for (int i = 0; i < totalPages; i++) {
newPageOrder.add(i);
}
// As all pages are already added, no need to check further
break;
} else if (element.matches("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
// Handle page order as a function
int coefficient = 0;
int constant = 0;
boolean coefficientExists = false;
boolean constantExists = false;
if (element.contains("n")) {
String[] parts = element.split("n");
if (!parts[0].equals("") && parts[0] != null) {
coefficient = Integer.parseInt(parts[0]);
coefficientExists = true;
}
if (parts.length > 1 && !parts[1].equals("") && parts[1] != null) {
constant = Integer.parseInt(parts[1]);
constantExists = true;
}
} else if (element.contains("+")) {
constant = Integer.parseInt(element.replace("+", ""));
constantExists = true;
}
for (int i = 1; i <= totalPages; i++) {
int pageNum = coefficientExists ? coefficient * i : i;
pageNum += constantExists ? constant : 0;
if (pageNum <= totalPages && pageNum > 0) {
newPageOrder.add(pageNum - 1);
}
}
} else if (element.contains("-")) {
// split the range into start and end page
String[] range = element.split("-");
int start = Integer.parseInt(range[0]);
int end = Integer.parseInt(range[1]);
// check if the end page is greater than total pages
if (end > totalPages) {
end = totalPages;
}
// loop through the range of pages
for (int j = start; j <= end; j++) {
// print the current index
newPageOrder.add(j - 1);
}
} else {
// if the element is a single page
newPageOrder.add(Integer.parseInt(element) - 1);
}
}
return newPageOrder;
}
public static boolean createDir(String path) {
Path folder = Paths.get(path);
if (!Files.exists(folder)) {
try {
Files.createDirectories(folder);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
}

View File

@@ -4,22 +4,29 @@ import java.awt.image.BufferedImage;
public class ImageProcessingUtils {
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
BufferedImage convertedImage;
switch (colorType) {
case "greyscale":
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
case "blackwhite":
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
default: // full color
convertedImage = sourceImage;
break;
}
return convertedImage;
}
static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
BufferedImage convertedImage;
switch (colorType) {
case "greyscale":
convertedImage =
new BufferedImage(
sourceImage.getWidth(),
sourceImage.getHeight(),
BufferedImage.TYPE_BYTE_GRAY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
case "blackwhite":
convertedImage =
new BufferedImage(
sourceImage.getWidth(),
sourceImage.getHeight(),
BufferedImage.TYPE_BYTE_BINARY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
default: // full color
convertedImage = sourceImage;
break;
}
return convertedImage;
}
}

View File

@@ -1,5 +1,3 @@
package stirling.software.SPDF.utils;
public class PDFManipulationUtils {
}
public class PDFManipulationUtils {}

View File

@@ -23,7 +23,9 @@ import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class PDFToFile {
public ResponseEntity<byte[]> processPdfToOfficeFormat(MultipartFile inputFile, String outputFormat, String libreOfficeFilter) throws IOException, InterruptedException {
public ResponseEntity<byte[]> processPdfToOfficeFormat(
MultipartFile inputFile, String outputFormat, String libreOfficeFilter)
throws IOException, InterruptedException {
if (!"application/pdf".equals(inputFile.getContentType())) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
@@ -34,7 +36,18 @@ public class PDFToFile {
String pdfBaseName = originalPdfFileName.substring(0, originalPdfFileName.lastIndexOf('.'));
// Validate output format
List<String> allowedFormats = Arrays.asList("doc", "docx", "odt", "ppt", "pptx", "odp", "rtf", "html", "xml", "txt:Text");
List<String> allowedFormats =
Arrays.asList(
"doc",
"docx",
"odt",
"ppt",
"pptx",
"odp",
"rtf",
"html",
"xml",
"txt:Text");
if (!allowedFormats.contains(outputFormat)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
@@ -47,15 +60,26 @@ public class PDFToFile {
try {
// Save the uploaded file to a temporary location
tempInputFile = Files.createTempFile("input_", ".pdf");
Files.copy(inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
Files.copy(
inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
// Prepare the output directory
tempOutputDir = Files.createTempDirectory("output_");
// Run the LibreOffice command
List<String> command = new ArrayList<>(
Arrays.asList("soffice", "--infilter=" + libreOfficeFilter, "--convert-to", outputFormat, "--outdir", tempOutputDir.toString(), tempInputFile.toString()));
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
List<String> command =
new ArrayList<>(
Arrays.asList(
"soffice",
"--infilter=" + libreOfficeFilter,
"--convert-to",
outputFormat,
"--outdir",
tempOutputDir.toString(),
tempInputFile.toString()));
ProcessExecutorResult returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE)
.runCommandWithOutputHandling(command);
// Get output files
List<File> outputFiles = Arrays.asList(tempOutputDir.toFile().listFiles());
@@ -89,11 +113,10 @@ public class PDFToFile {
} finally {
// Clean up the temporary files
if (tempInputFile != null)
Files.delete(tempInputFile);
if (tempOutputDir != null)
FileUtils.deleteDirectory(tempOutputDir.toFile());
if (tempInputFile != null) Files.delete(tempInputFile);
if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
}
return WebResponseUtils.bytesToWebResponse(fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
return WebResponseUtils.bytesToWebResponse(
fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
}
}

View File

@@ -5,7 +5,6 @@ import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -37,38 +36,35 @@ public class PdfUtils {
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
public static PDRectangle textToPageSize(String size) {
switch (size.toUpperCase()) {
case "A0":
return PDRectangle.A0;
case "A1":
return PDRectangle.A1;
case "A2":
return PDRectangle.A2;
case "A3":
return PDRectangle.A3;
case "A4":
return PDRectangle.A4;
case "A5":
return PDRectangle.A5;
case "A6":
return PDRectangle.A6;
case "LETTER":
return PDRectangle.LETTER;
case "LEGAL":
return PDRectangle.LEGAL;
default:
throw new IllegalArgumentException("Invalid standard page size: " + size);
}
}
public static PDRectangle textToPageSize(String size) {
switch (size.toUpperCase()) {
case "A0":
return PDRectangle.A0;
case "A1":
return PDRectangle.A1;
case "A2":
return PDRectangle.A2;
case "A3":
return PDRectangle.A3;
case "A4":
return PDRectangle.A4;
case "A5":
return PDRectangle.A5;
case "A6":
return PDRectangle.A6;
case "LETTER":
return PDRectangle.LETTER;
case "LEGAL":
return PDRectangle.LEGAL;
default:
throw new IllegalArgumentException("Invalid standard page size: " + size);
}
}
public static boolean hasImages(PDDocument document, String pagesToCheck) throws IOException {
String[] pageOrderArr = pagesToCheck.split(",");
List<Integer> pageList = GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
List<Integer> pageList =
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
for (int pageNumber : pageList) {
PDPage page = document.getPage(pageNumber);
@@ -80,9 +76,11 @@ public class PdfUtils {
return false;
}
public static boolean hasText(PDDocument document, String pageNumbersToCheck, String phrase) throws IOException {
public static boolean hasText(PDDocument document, String pageNumbersToCheck, String phrase)
throws IOException {
String[] pageOrderArr = pageNumbersToCheck.split(",");
List<Integer> pageList = GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
List<Integer> pageList =
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
for (int pageNumber : pageList) {
PDPage page = document.getPage(pageNumber);
@@ -94,15 +92,11 @@ public class PdfUtils {
return false;
}
public static boolean hasImagesOnPage(PDPage page) throws IOException {
ImageFinder imageFinder = new ImageFinder(page);
imageFinder.processPage(page);
return imageFinder.hasImages();
}
public static boolean hasTextOnPage(PDPage page, String phrase) throws IOException {
PDFTextStripper textStripper = new PDFTextStripper();
@@ -113,12 +107,12 @@ public class PdfUtils {
return pageText.contains(phrase);
}
public boolean containsTextInFile(PDDocument pdfDocument, String text, String pagesToCheck) throws IOException {
public boolean containsTextInFile(PDDocument pdfDocument, String text, String pagesToCheck)
throws IOException {
PDFTextStripper textStripper = new PDFTextStripper();
String pdfText = "";
if(pagesToCheck == null || pagesToCheck.equals("all")) {
if (pagesToCheck == null || pagesToCheck.equals("all")) {
pdfText = textStripper.getText(pdfDocument);
} else {
// remove whitespaces
@@ -152,15 +146,12 @@ public class PdfUtils {
return pdfText.contains(text);
}
public boolean pageCount(PDDocument pdfDocument, int pageCount, String comparator) throws IOException {
public boolean pageCount(PDDocument pdfDocument, int pageCount, String comparator)
throws IOException {
int actualPageCount = pdfDocument.getNumberOfPages();
pdfDocument.close();
switch(comparator.toLowerCase()) {
switch (comparator.toLowerCase()) {
case "greater":
return actualPageCount > pageCount;
case "equal":
@@ -168,7 +159,8 @@ public class PdfUtils {
case "less":
return actualPageCount < pageCount;
default:
throw new IllegalArgumentException("Invalid comparator. Only 'greater', 'equal', and 'less' are supported.");
throw new IllegalArgumentException(
"Invalid comparator. Only 'greater', 'equal', and 'less' are supported.");
}
}
@@ -189,12 +181,15 @@ public class PdfUtils {
// Checks if the actual page size matches the expected page size
return actualPageWidth == expectedPageWidth && actualPageHeight == expectedPageHeight;
}
public static byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage, int DPI, String filename) throws IOException, Exception {
public static byte[] convertFromPdf(
byte[] inputStream,
String imageType,
ImageType colorType,
boolean singleImage,
int DPI,
String filename)
throws IOException, Exception {
try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
int pageCount = document.getNumberOfPages();
@@ -203,7 +198,8 @@ public class PdfUtils {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (singleImage) {
if (imageType.toLowerCase().equals("tiff") || imageType.toLowerCase().equals("tif")) {
if (imageType.toLowerCase().equals("tiff")
|| imageType.toLowerCase().equals("tif")) {
// Write the images to the output stream as a TIFF with multiple frames
ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
ImageWriteParam param = writer.getDefaultWriteParam();
@@ -227,13 +223,17 @@ public class PdfUtils {
} else {
// Combine all images into a single big image
BufferedImage image = pdfRenderer.renderImageWithDPI(0, DPI, colorType);
BufferedImage combined = new BufferedImage(image.getWidth(), image.getHeight() * pageCount, BufferedImage.TYPE_INT_RGB);
BufferedImage combined =
new BufferedImage(
image.getWidth(),
image.getHeight() * pageCount,
BufferedImage.TYPE_INT_RGB);
Graphics g = combined.getGraphics();
for (int i = 0; i < pageCount; ++i) {
if (i != 0) {
image = pdfRenderer.renderImageWithDPI(i, DPI, colorType);
}
}
g.drawImage(image, 0, i * image.getHeight(), null);
}
@@ -252,7 +252,12 @@ public class PdfUtils {
ImageIO.write(image, imageType, baosImage);
// Add the image to the zip file
zos.putNextEntry(new ZipEntry(String.format(filename + "_%d.%s", i + 1, imageType.toLowerCase())));
zos.putNextEntry(
new ZipEntry(
String.format(
filename + "_%d.%s",
i + 1,
imageType.toLowerCase())));
zos.write(baosImage.toByteArray());
}
}
@@ -267,28 +272,37 @@ public class PdfUtils {
throw e;
}
}
public static byte[] imageToPdf(MultipartFile[] files, String fitOption, boolean autoRotate, String colorType) throws IOException {
public static byte[] imageToPdf(
MultipartFile[] files, String fitOption, boolean autoRotate, String colorType)
throws IOException {
try (PDDocument doc = new PDDocument()) {
for (MultipartFile file : files) {
String contentType = file.getContentType();
String contentType = file.getContentType();
String originalFilename = file.getOriginalFilename();
if (originalFilename != null && (originalFilename.toLowerCase().endsWith(".tiff") || originalFilename.toLowerCase().endsWith(".tif")) ) {
if (originalFilename != null
&& (originalFilename.toLowerCase().endsWith(".tiff")
|| originalFilename.toLowerCase().endsWith(".tif"))) {
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
reader.setInput(ImageIO.createImageInputStream(file.getInputStream()));
int numPages = reader.getNumImages(true);
for (int i = 0; i < numPages; i++) {
BufferedImage pageImage = reader.read(i);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(pageImage, colorType);
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
BufferedImage convertedImage =
ImageProcessingUtils.convertColorType(pageImage, colorType);
PDImageXObject pdImage =
LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, fitOption, autoRotate);
}
} else {
BufferedImage image = ImageIO.read(file.getInputStream());
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(image, colorType);
BufferedImage convertedImage =
ImageProcessingUtils.convertColorType(image, colorType);
// Use JPEGFactory if it's JPEG since JPEG is lossy
PDImageXObject pdImage = (contentType != null && contentType.equals("image/jpeg"))
? JPEGFactory.createFromImage(doc, convertedImage)
: LosslessFactory.createFromImage(doc, convertedImage);
PDImageXObject pdImage =
(contentType != null && contentType.equals("image/jpeg"))
? JPEGFactory.createFromImage(doc, convertedImage)
: LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, fitOption, autoRotate);
}
}
@@ -299,11 +313,13 @@ public class PdfUtils {
}
}
private static void addImageToDocument(PDDocument doc, PDImageXObject image, String fitOption, boolean autoRotate) throws IOException {
private static void addImageToDocument(
PDDocument doc, PDImageXObject image, String fitOption, boolean autoRotate)
throws IOException {
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
System.out.println(fitOption);
System.out.println(fitOption);
if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
@@ -335,7 +351,12 @@ public class PdfUtils {
float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2;
float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2;
contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor);
contentStream.drawImage(
image,
xPos,
yPos,
image.getWidth() * scaleFactor,
image.getHeight() * scaleFactor);
}
} catch (IOException e) {
logger.error("Error adding image to PDF", e);
@@ -343,8 +364,9 @@ public class PdfUtils {
}
}
public static byte[] overlayImage(byte[] pdfBytes, byte[] imageBytes, float x, float y, boolean everyPage) throws IOException {
public static byte[] overlayImage(
byte[] pdfBytes, byte[] imageBytes, float x, float y, boolean everyPage)
throws IOException {
PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfBytes));
@@ -352,7 +374,9 @@ public class PdfUtils {
int pages = document.getNumberOfPages();
for (int i = 0; i < pages; i++) {
PDPage page = document.getPage(i);
try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true)) {
try (PDPageContentStream contentStream =
new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true)) {
// Create an image object from the image bytes
PDImageXObject image = PDImageXObject.createFromByteArray(document, imageBytes, "");
// Draw the image onto the page at the specified x and y coordinates
@@ -366,7 +390,6 @@ public class PdfUtils {
logger.error("Error overlaying image onto PDF", e);
throw e;
}
}
// Create a ByteArrayOutputStream to save the PDF to
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -374,8 +397,4 @@ public class PdfUtils {
logger.info("PDF successfully saved to byte array");
return baos.toByteArray();
}
}

View File

@@ -14,22 +14,29 @@ import java.util.concurrent.Semaphore;
public class ProcessExecutor {
public enum Processes {
LIBRE_OFFICE, OCR_MY_PDF, PYTHON_OPENCV, GHOSTSCRIPT, WEASYPRINT
LIBRE_OFFICE,
OCR_MY_PDF,
PYTHON_OPENCV,
GHOSTSCRIPT,
WEASYPRINT
}
private static final Map<Processes, ProcessExecutor> instances = new ConcurrentHashMap<>();
public static ProcessExecutor getInstance(Processes processType) {
return instances.computeIfAbsent(processType, key -> {
int semaphoreLimit = switch (key) {
case LIBRE_OFFICE -> 1;
case OCR_MY_PDF -> 2;
case PYTHON_OPENCV -> 8;
case GHOSTSCRIPT -> 16;
case WEASYPRINT -> 16;
};
return new ProcessExecutor(semaphoreLimit);
});
return instances.computeIfAbsent(
processType,
key -> {
int semaphoreLimit =
switch (key) {
case LIBRE_OFFICE -> 1;
case OCR_MY_PDF -> 2;
case PYTHON_OPENCV -> 8;
case GHOSTSCRIPT -> 16;
case WEASYPRINT -> 16;
};
return new ProcessExecutor(semaphoreLimit);
});
}
private final Semaphore semaphore;
@@ -37,10 +44,14 @@ public class ProcessExecutor {
private ProcessExecutor(int semaphoreLimit) {
this.semaphore = new Semaphore(semaphoreLimit);
}
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command) throws IOException, InterruptedException {
return runCommandWithOutputHandling(command, null);
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command)
throws IOException, InterruptedException {
return runCommandWithOutputHandling(command, null);
}
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command, File workingDirectory) throws IOException, InterruptedException {
public ProcessExecutorResult runCommandWithOutputHandling(
List<String> command, File workingDirectory) throws IOException, InterruptedException {
int exitCode = 1;
String messages = "";
semaphore.acquire();
@@ -48,7 +59,7 @@ public class ProcessExecutor {
System.out.print("Running command: " + String.join(" ", command));
ProcessBuilder processBuilder = new ProcessBuilder(command);
// Use the working directory if it's set
if (workingDirectory != null) {
processBuilder.directory(workingDirectory);
@@ -59,27 +70,39 @@ public class ProcessExecutor {
List<String> errorLines = new ArrayList<>();
List<String> outputLines = new ArrayList<>();
Thread errorReaderThread = new Thread(() -> {
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = errorReader.readLine()) != null) {
errorLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread errorReaderThread =
new Thread(
() -> {
try (BufferedReader errorReader =
new BufferedReader(
new InputStreamReader(
process.getErrorStream(),
StandardCharsets.UTF_8))) {
String line;
while ((line = errorReader.readLine()) != null) {
errorLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread outputReaderThread = new Thread(() -> {
try (BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = outputReader.readLine()) != null) {
outputLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread outputReaderThread =
new Thread(
() -> {
try (BufferedReader outputReader =
new BufferedReader(
new InputStreamReader(
process.getInputStream(),
StandardCharsets.UTF_8))) {
String line;
while ((line = outputReader.readLine()) != null) {
outputLines.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
});
errorReaderThread.start();
outputReaderThread.start();
@@ -90,7 +113,7 @@ public class ProcessExecutor {
// Wait for the reader threads to finish
errorReaderThread.join();
outputReaderThread.join();
if (outputLines.size() > 0) {
String outputMessage = String.join("\n", outputLines);
messages += outputMessage;
@@ -102,7 +125,11 @@ public class ProcessExecutor {
messages += errorMessage;
System.out.println("Command error output:\n" + errorMessage);
if (exitCode != 0) {
throw new IOException("Command process failed with exit code " + exitCode + ". Error message: " + errorMessage);
throw new IOException(
"Command process failed with exit code "
+ exitCode
+ ". Error message: "
+ errorMessage);
}
}
} finally {
@@ -110,26 +137,30 @@ public class ProcessExecutor {
}
return new ProcessExecutorResult(exitCode, messages);
}
public class ProcessExecutorResult{
int rc;
String messages;
public ProcessExecutorResult(int rc, String messages) {
this.rc = rc;
this.messages = messages;
}
public int getRc() {
return rc;
}
public void setRc(int rc) {
this.rc = rc;
}
public String getMessages() {
return messages;
}
public void setMessages(String messages) {
this.messages = messages;
}
public class ProcessExecutorResult {
int rc;
String messages;
public ProcessExecutorResult(int rc, String messages) {
this.rc = rc;
this.messages = messages;
}
public int getRc() {
return rc;
}
public void setRc(int rc) {
this.rc = rc;
}
public String getMessages() {
return messages;
}
public void setMessages(String messages) {
this.messages = messages;
}
}
}

View File

@@ -4,46 +4,35 @@ import java.util.List;
public class PropertyConfigs {
public static boolean getBooleanValue(List<String> keys, boolean defaultValue) {
for (String key : keys) {
String value = System.getProperty(key);
if (value == null)
value = System.getenv(key);
if (value != null)
return Boolean.valueOf(value);
}
return defaultValue;
}
public static boolean getBooleanValue(List<String> keys, boolean defaultValue) {
for (String key : keys) {
String value = System.getProperty(key);
if (value == null) value = System.getenv(key);
public static String getStringValue(List<String> keys, String defaultValue) {
for (String key : keys) {
String value = System.getProperty(key);
if (value == null)
value = System.getenv(key);
if (value != null)
return value;
}
return defaultValue;
}
if (value != null) return Boolean.valueOf(value);
}
return defaultValue;
}
public static boolean getBooleanValue(String key, boolean defaultValue) {
public static String getStringValue(List<String> keys, String defaultValue) {
for (String key : keys) {
String value = System.getProperty(key);
if (value == null) value = System.getenv(key);
if (value != null) return value;
}
return defaultValue;
}
public static boolean getBooleanValue(String key, boolean defaultValue) {
String value = System.getProperty(key);
if (value == null)
value = System.getenv(key);
if (value == null) value = System.getenv(key);
return (value != null) ? Boolean.valueOf(value) : defaultValue;
}
public static String getStringValue(String key, String defaultValue) {
public static String getStringValue(String key, String defaultValue) {
String value = System.getProperty(key);
if (value == null)
value = System.getenv(key);
if (value == null) value = System.getenv(key);
return (value != null) ? value : defaultValue;
}
}

View File

@@ -2,15 +2,13 @@ package stirling.software.SPDF.utils;
public class RequestUriUtils {
public static boolean isStaticResource(String requestURI) {
return requestURI.startsWith("/css/")
|| requestURI.startsWith("/js/")
|| requestURI.startsWith("/images/")
|| requestURI.startsWith("/public/")
|| requestURI.startsWith("/pdfjs/")
|| requestURI.endsWith(".svg");
}
public static boolean isStaticResource(String requestURI) {
return requestURI.startsWith("/css/")
|| requestURI.startsWith("/js/")
|| requestURI.startsWith("/images/")
|| requestURI.startsWith("/public/")
|| requestURI.startsWith("/pdfjs/")
|| requestURI.endsWith(".svg");
}
}

View File

@@ -12,53 +12,56 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
public class WebResponseUtils {
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName) throws IOException {
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName);
}
public static ResponseEntity<byte[]> boasToWebResponse(
ByteArrayOutputStream baos, String docName) throws IOException {
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName);
}
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName, MediaType mediaType) throws IOException {
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName, mediaType);
}
public static ResponseEntity<byte[]> boasToWebResponse(
ByteArrayOutputStream baos, String docName, MediaType mediaType) throws IOException {
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), docName, mediaType);
}
public static ResponseEntity<byte[]> multiPartFileToWebResponse(MultipartFile file)
throws IOException {
String fileName = file.getOriginalFilename();
MediaType mediaType = MediaType.parseMediaType(file.getContentType());
public static ResponseEntity<byte[]> multiPartFileToWebResponse(MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
MediaType mediaType = MediaType.parseMediaType(file.getContentType());
byte[] bytes = file.getBytes();
byte[] bytes = file.getBytes();
return bytesToWebResponse(bytes, fileName, mediaType);
}
return bytesToWebResponse(bytes, fileName, mediaType);
}
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName, MediaType mediaType) throws IOException {
// Return the PDF as a response
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
headers.setContentLength(bytes.length);
String encodedDocName = URLEncoder.encode(docName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
headers.setContentDispositionFormData("attachment", encodedDocName);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
public static ResponseEntity<byte[]> bytesToWebResponse(
byte[] bytes, String docName, MediaType mediaType) throws IOException {
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName) throws IOException {
return bytesToWebResponse(bytes, docName, MediaType.APPLICATION_PDF);
}
// Return the PDF as a response
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
headers.setContentLength(bytes.length);
String encodedDocName =
URLEncoder.encode(docName, StandardCharsets.UTF_8.toString())
.replaceAll("\\+", "%20");
headers.setContentDispositionFormData("attachment", encodedDocName);
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
public static ResponseEntity<byte[]> pdfDocToWebResponse(PDDocument document, String docName) throws IOException {
// Open Byte Array and save document to it
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
// Close the document
document.close();
return boasToWebResponse(baos, docName);
}
public static ResponseEntity<byte[]> bytesToWebResponse(byte[] bytes, String docName)
throws IOException {
return bytesToWebResponse(bytes, docName, MediaType.APPLICATION_PDF);
}
public static ResponseEntity<byte[]> pdfDocToWebResponse(PDDocument document, String docName)
throws IOException {
// Open Byte Array and save document to it
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
// Close the document
document.close();
return boasToWebResponse(baos, docName);
}
}