diff --git a/build.gradle b/build.gradle index 06141dba..3cd1afc6 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,7 @@ plugins { import com.github.jk1.license.render.* group = 'stirling.software' - -version = '0.22.2' +version = '0.22.3' sourceCompatibility = '17' repositories { diff --git a/chart/stirling-pdf/Chart.yaml b/chart/stirling-pdf/Chart.yaml index 94bc50fc..f355b44c 100644 --- a/chart/stirling-pdf/Chart.yaml +++ b/chart/stirling-pdf/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 0.20.2 +appVersion: 0.22.3 description: locally hosted web application that allows you to perform various operations on PDF files home: https://github.com/Stirling-Tools/Stirling-PDF keywords: diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java index 2dc6c8a3..f0fb7b02 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java @@ -130,7 +130,7 @@ public class AutoRenameController { // Sanitize the header string by removing characters not allowed in a filename. if (header != null && header.length() < 255) { - header = header.replaceAll("[/\\\\?%*:|\"<>]", ""); + header = header.replaceAll("[/\\\\?%*:|\"<>]", "").trim(); return WebResponseUtils.pdfDocToWebResponse(document, header + ".pdf"); } else { logger.info("File has no good title to be found"); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java index 32f39c04..0b578d8f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java @@ -58,7 +58,7 @@ public class AutoSplitPdfController { PDDocument document = Loader.loadPDF(file.getBytes()); PDFRenderer pdfRenderer = new PDFRenderer(document); - + pdfRenderer.setSubsamplingAllowed(true); List splitDocuments = new ArrayList<>(); List splitDocumentsBoas = new ArrayList<>(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java index a813ba79..eaac72a0 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java @@ -59,7 +59,7 @@ public class BlankPageController { List pagesToKeepIndex = new ArrayList<>(); int pageIndex = 0; PDFRenderer pdfRenderer = new PDFRenderer(document); - + pdfRenderer.setSubsamplingAllowed(true); for (PDPage page : pages) { logger.info("checking page " + pageIndex); textStripper.setStartPage(pageIndex + 1); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java index 82a2c72f..9e3d6a99 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java @@ -2,9 +2,7 @@ package stirling.software.SPDF.controller.api.misc; import java.awt.Image; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -75,194 +73,208 @@ public class CompressController { long inputFileSize = Files.size(tempInputFile); // Prepare the output file path - Path tempOutputFile = Files.createTempFile("output_", ".pdf"); - - // Determine initial optimization level based on expected size reduction, only if in - // autoMode - if (autoMode) { - double sizeReductionRatio = expectedOutputSize / (double) inputFileSize; - if (sizeReductionRatio > 0.7) { - optimizeLevel = 1; - } else if (sizeReductionRatio > 0.5) { - optimizeLevel = 2; - } else if (sizeReductionRatio > 0.35) { - optimizeLevel = 3; - } else { - optimizeLevel = 3; - } - } - - boolean sizeMet = false; - while (!sizeMet && optimizeLevel <= 4) { - // Prepare the Ghostscript command - List command = new ArrayList<>(); - command.add("gs"); - command.add("-sDEVICE=pdfwrite"); - command.add("-dCompatibilityLevel=1.4"); - - switch (optimizeLevel) { - case 1: - command.add("-dPDFSETTINGS=/prepress"); - break; - case 2: - command.add("-dPDFSETTINGS=/printer"); - break; - case 3: - command.add("-dPDFSETTINGS=/ebook"); - break; - case 4: - command.add("-dPDFSETTINGS=/screen"); - break; - default: - command.add("-dPDFSETTINGS=/default"); - } - - command.add("-dNOPAUSE"); - command.add("-dQUIET"); - command.add("-dBATCH"); - command.add("-sOutputFile=" + tempOutputFile.toString()); - command.add(tempInputFile.toString()); - - ProcessExecutorResult returnCode = - ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT) - .runCommandWithOutputHandling(command); - - // Check if file size is within expected size or not auto mode so instantly finish - long outputFileSize = Files.size(tempOutputFile); - if (outputFileSize <= expectedOutputSize || !autoMode) { - sizeMet = true; - } else { - // Increase optimization level for next iteration - optimizeLevel++; - if (autoMode && optimizeLevel > 3) { - System.out.println("Skipping level 4 due to bad results in auto mode"); - sizeMet = true; - } else if (optimizeLevel == 5) { + Path tempOutputFile = null; + byte[] pdfBytes; + try { + tempOutputFile = Files.createTempFile("output_", ".pdf"); + // Determine initial optimization level based on expected size reduction, only if in + // autoMode + if (autoMode) { + double sizeReductionRatio = expectedOutputSize / (double) inputFileSize; + if (sizeReductionRatio > 0.7) { + optimizeLevel = 1; + } else if (sizeReductionRatio > 0.5) { + optimizeLevel = 2; + } else if (sizeReductionRatio > 0.35) { + optimizeLevel = 3; } else { - System.out.println( - "Increasing ghostscript optimisation level to " + optimizeLevel); + optimizeLevel = 3; } } - } - if (expectedOutputSize != null && autoMode) { - long outputFileSize = Files.size(tempOutputFile); - if (outputFileSize > expectedOutputSize) { - try (PDDocument doc = Loader.loadPDF(new File(tempOutputFile.toString()))) { - long previousFileSize = 0; - double scaleFactor = 1.0; - while (true) { - for (PDPage page : doc.getPages()) { - PDResources res = page.getResources(); + boolean sizeMet = false; + while (!sizeMet && optimizeLevel <= 4) { + // Prepare the Ghostscript command + List command = new ArrayList<>(); + command.add("gs"); + command.add("-sDEVICE=pdfwrite"); + command.add("-dCompatibilityLevel=1.4"); - for (COSName name : res.getXObjectNames()) { - PDXObject xobj = res.getXObject(name); - if (xobj instanceof PDImageXObject) { - PDImageXObject image = (PDImageXObject) xobj; + switch (optimizeLevel) { + case 1: + command.add("-dPDFSETTINGS=/prepress"); + break; + case 2: + command.add("-dPDFSETTINGS=/printer"); + break; + case 3: + command.add("-dPDFSETTINGS=/ebook"); + break; + case 4: + command.add("-dPDFSETTINGS=/screen"); + break; + default: + command.add("-dPDFSETTINGS=/default"); + } - // Get the image in BufferedImage format - BufferedImage bufferedImage = image.getImage(); + command.add("-dNOPAUSE"); + command.add("-dQUIET"); + command.add("-dBATCH"); + command.add("-sOutputFile=" + tempOutputFile.toString()); + command.add(tempInputFile.toString()); - // Calculate the new dimensions - int newWidth = (int) (bufferedImage.getWidth() * scaleFactor); - int newHeight = (int) (bufferedImage.getHeight() * scaleFactor); + ProcessExecutorResult returnCode = + ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT) + .runCommandWithOutputHandling(command); - // If the new dimensions are zero, skip this iteration - if (newWidth == 0 || newHeight == 0) { - continue; + // Check if file size is within expected size or not auto mode so instantly finish + long outputFileSize = Files.size(tempOutputFile); + if (outputFileSize <= expectedOutputSize || !autoMode) { + sizeMet = true; + } else { + // Increase optimization level for next iteration + optimizeLevel++; + if (autoMode && optimizeLevel > 4) { + System.out.println("Skipping level 5 due to bad results in auto mode"); + sizeMet = true; + } else { + System.out.println( + "Increasing ghostscript optimisation level to " + optimizeLevel); + } + } + } + + if (expectedOutputSize != null && autoMode) { + long outputFileSize = Files.size(tempOutputFile); + byte[] fileBytes = Files.readAllBytes(tempOutputFile); + if (outputFileSize > expectedOutputSize) { + try (PDDocument doc = Loader.loadPDF(fileBytes)) { + long previousFileSize = 0; + double scaleFactorConst = 0.9f; + double scaleFactor = 0.9f; + while (true) { + for (PDPage page : doc.getPages()) { + PDResources res = page.getResources(); + if (res != null && res.getXObjectNames() != null) { + for (COSName name : res.getXObjectNames()) { + PDXObject xobj = res.getXObject(name); + if (xobj != null && xobj instanceof PDImageXObject) { + PDImageXObject image = (PDImageXObject) xobj; + + // Get the image in BufferedImage format + BufferedImage bufferedImage = image.getImage(); + + // Calculate the new dimensions + int newWidth = + (int) + (bufferedImage.getWidth() + * scaleFactorConst); + int newHeight = + (int) + (bufferedImage.getHeight() + * scaleFactorConst); + + // If the new dimensions are zero, skip this iteration + if (newWidth == 0 || newHeight == 0) { + continue; + } + + // Otherwise, proceed with the scaling + Image scaledImage = + bufferedImage.getScaledInstance( + newWidth, + newHeight, + Image.SCALE_SMOOTH); + + // Convert the scaled image back to a BufferedImage + BufferedImage scaledBufferedImage = + new BufferedImage( + newWidth, + newHeight, + BufferedImage.TYPE_INT_RGB); + scaledBufferedImage + .getGraphics() + .drawImage(scaledImage, 0, 0, null); + + // Compress the scaled image + ByteArrayOutputStream compressedImageStream = + new ByteArrayOutputStream(); + ImageIO.write( + scaledBufferedImage, + "jpeg", + compressedImageStream); + byte[] imageBytes = compressedImageStream.toByteArray(); + compressedImageStream.close(); + + PDImageXObject compressedImage = + PDImageXObject.createFromByteArray( + doc, + imageBytes, + image.getCOSObject().toString()); + + // Replace the image in the resources with the + // compressed + // version + res.put(name, compressedImage); + } } - - // Otherwise, proceed with the scaling - Image scaledImage = - bufferedImage.getScaledInstance( - newWidth, newHeight, Image.SCALE_SMOOTH); - - // Convert the scaled image back to a BufferedImage - BufferedImage scaledBufferedImage = - new BufferedImage( - newWidth, - newHeight, - BufferedImage.TYPE_INT_RGB); - scaledBufferedImage - .getGraphics() - .drawImage(scaledImage, 0, 0, null); - - // Compress the scaled image - ByteArrayOutputStream compressedImageStream = - new ByteArrayOutputStream(); - ImageIO.write( - scaledBufferedImage, "jpeg", compressedImageStream); - byte[] imageBytes = compressedImageStream.toByteArray(); - compressedImageStream.close(); - - // Convert compressed image back to PDImageXObject - ByteArrayInputStream bais = - new ByteArrayInputStream(imageBytes); - PDImageXObject compressedImage = - PDImageXObject.createFromByteArray( - doc, - imageBytes, - image.getCOSObject().toString()); - - // Replace the image in the resources with the compressed - // version - res.put(name, compressedImage); } } - } - // save the document to tempOutputFile again - doc.save(tempOutputFile.toString()); + // save the document to tempOutputFile again + doc.save(tempOutputFile.toString()); - long currentSize = Files.size(tempOutputFile); - // Check if the overall PDF size is still larger than expectedOutputSize - if (currentSize > expectedOutputSize) { - // Log the current file size and scaleFactor + long currentSize = Files.size(tempOutputFile); + // Check if the overall PDF size is still larger than expectedOutputSize + if (currentSize > expectedOutputSize) { + // Log the current file size and scaleFactor - System.out.println( - "Current file size: " - + FileUtils.byteCountToDisplaySize(currentSize)); - System.out.println("Current scale factor: " + scaleFactor); + System.out.println( + "Current file size: " + + FileUtils.byteCountToDisplaySize(currentSize)); + System.out.println("Current scale factor: " + scaleFactor); - // The file is still too large, reduce scaleFactor and try again - scaleFactor *= 0.9; // reduce scaleFactor by 10% - // Avoid scaleFactor being too small, causing the image to shrink to 0 - if (scaleFactor < 0.2 || previousFileSize == currentSize) { - throw new RuntimeException( - "Could not reach the desired size without excessively degrading image quality, lowest size recommended is " - + FileUtils.byteCountToDisplaySize(currentSize) - + ", " - + currentSize - + " bytes"); + // The file is still too large, reduce scaleFactor and try again + scaleFactor *= 0.9f; // reduce scaleFactor by 10% + // Avoid scaleFactor being too small, causing the image to shrink to + // 0 + if (scaleFactor < 0.2f || previousFileSize == currentSize) { + throw new RuntimeException( + "Could not reach the desired size without excessively degrading image quality, lowest size recommended is " + + FileUtils.byteCountToDisplaySize(currentSize) + + ", " + + currentSize + + " bytes"); + } + previousFileSize = currentSize; + } else { + // The file is small enough, break the loop + break; } - previousFileSize = currentSize; - } else { - // The file is small enough, break the loop - break; } } } } + + // Read the optimized PDF file + pdfBytes = Files.readAllBytes(tempOutputFile); + + // Check if optimized file is larger than the original + if (pdfBytes.length > inputFileSize) { + // Log the occurrence + logger.warn( + "Optimized file is larger than the original. Returning the original file instead."); + + // Read the original file again + pdfBytes = Files.readAllBytes(tempInputFile); + } + } finally { + // Clean up the temporary files + Files.delete(tempInputFile); + Files.delete(tempOutputFile); } - // Read the optimized PDF file - byte[] pdfBytes = Files.readAllBytes(tempOutputFile); - - // Check if optimized file is larger than the original - if (pdfBytes.length > inputFileSize) { - // Log the occurrence - logger.warn( - "Optimized file is larger than the original. Returning the original file instead."); - - // Read the original file again - pdfBytes = Files.readAllBytes(tempInputFile); - } - - // Clean up the temporary files - Files.delete(tempInputFile); - Files.delete(tempOutputFile); - // Return the optimized PDF as a response String outputFilename = Filenames.toSimpleFileName(inputFile.getOriginalFilename()) diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java index 855826db..be82364f 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java @@ -84,6 +84,7 @@ public class ExtractImageScansController { // Load PDF document try (PDDocument document = Loader.loadPDF(form.getFileInput().getBytes())) { PDFRenderer pdfRenderer = new PDFRenderer(document); + pdfRenderer.setSubsamplingAllowed(true); int pageCount = document.getNumberOfPages(); images = new ArrayList<>(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java index 789bf17e..a93b64f2 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java @@ -60,6 +60,7 @@ public class FakeScanControllerWIP { PDDocument document = Loader.loadPDF(inputFile.getBytes()); PDFRenderer pdfRenderer = new PDFRenderer(document); + pdfRenderer.setSubsamplingAllowed(true); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); ImageIO.write(image, "png", new File("scanned-" + (page + 1) + ".png")); diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index 0a53daf0..dfa45096 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -12,7 +12,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ModelAttribute; @@ -50,9 +49,6 @@ public class PipelineController { @PostMapping("/handleData") public ResponseEntity handleData(@ModelAttribute HandleDataRequest request) throws JsonMappingException, JsonProcessingException { - if (!Boolean.TRUE.equals(applicationProperties.getSystem().getEnableAlphaFunctionality())) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } MultipartFile[] files = request.getFileInput(); String jsonString = request.getJson(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java index 0f482647..8a2a67c0 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java @@ -83,6 +83,7 @@ public class RedactController { if (convertPDFToImage) { PDDocument imageDocument = new PDDocument(); PDFRenderer pdfRenderer = new PDFRenderer(document); + pdfRenderer.setSubsamplingAllowed(true); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); PDPage newPage = new PDPage(new PDRectangle(bim.getWidth(), bim.getHeight())); diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index 6dfbf044..f33df3aa 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -54,33 +54,32 @@ public class SanitizeController { boolean removeLinks = request.isRemoveLinks(); boolean removeFonts = request.isRemoveFonts(); - try (PDDocument document = Loader.loadPDF(inputFile.getBytes())) { - if (removeJavaScript) { - sanitizeJavaScript(document); - } - - if (removeEmbeddedFiles) { - sanitizeEmbeddedFiles(document); - } - - if (removeMetadata) { - sanitizeMetadata(document); - } - - if (removeLinks) { - sanitizeLinks(document); - } - - if (removeFonts) { - sanitizeFonts(document); - } - - return WebResponseUtils.pdfDocToWebResponse( - document, - Filenames.toSimpleFileName(inputFile.getOriginalFilename()) - .replaceFirst("[.][^.]+$", "") - + "_sanitized.pdf"); + PDDocument document = Loader.loadPDF(inputFile.getBytes()); + if (removeJavaScript) { + sanitizeJavaScript(document); } + + if (removeEmbeddedFiles) { + sanitizeEmbeddedFiles(document); + } + + if (removeMetadata) { + sanitizeMetadata(document); + } + + if (removeLinks) { + sanitizeLinks(document); + } + + if (removeFonts) { + sanitizeFonts(document); + } + + return WebResponseUtils.pdfDocToWebResponse( + document, + Filenames.toSimpleFileName(inputFile.getOriginalFilename()) + .replaceFirst("[.][^.]+$", "") + + "_sanitized.pdf"); } private void sanitizeJavaScript(PDDocument document) throws IOException { diff --git a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java index b0bb1aee..18e890c4 100644 --- a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java +++ b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java @@ -136,6 +136,7 @@ public class GeneralUtils { int offset = oneBased ? 1 : 0; for (String page : pages) { if ("all".equalsIgnoreCase(page)) { + for (int i = 0; i < totalPages; i++) { result.add(i + offset); } diff --git a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java index 77814340..3d16f131 100644 --- a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java +++ b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java @@ -214,6 +214,7 @@ public class PdfUtils { throws IOException, Exception { try (PDDocument document = Loader.loadPDF(inputStream)) { PDFRenderer pdfRenderer = new PDFRenderer(document); + pdfRenderer.setSubsamplingAllowed(true); int pageCount = document.getNumberOfPages(); // Create a ByteArrayOutputStream to save the image(s) to diff --git a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java index 2c81dce5..595ada58 100644 --- a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java +++ b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java @@ -189,7 +189,11 @@ public class ProcessExecutor { } } } else if (exitCode != 0) { - throw new IOException("Command process failed with exit code " + exitCode); + throw new IOException( + "Command process failed with exit code " + + exitCode + + "\nLogs: " + + messages); } } finally { semaphore.release(); diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 579e649c..e69de29b 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,11 +0,0 @@ -fileToPDF.fileTypesList=Microsoft Word: (DOC, DOCX, DOT, DOTX)
\ -Microsoft Excel: (CSV, XLS, XLSX, XLT, XLTX, SLK, DIF)
\ -Microsoft PowerPoint: (PPT, PPTX)
\ -OpenDocument Formats: (ODT, OTT, ODS, OTS, ODP, OTP, ODG, OTG)
\ -Plain Text: (TXT, TEXT, XML)
\ -Rich Text Format: (RTF)
\ -Images: (BMP, GIF, JPEG, PNG, TIF, PBM, PGM, PPM, RAS, XBM, XPM, SVG, SVM, WMF)
\ -HTML: (HTML)
\ -Lotus Word Pro: (LWP)
\ -StarOffice formats: (SDA, SDC, SDD, SDW, STC, STD, STI, STW, SXD, SXG, SXI, SXW)
\ -Other formats: (DBF, FODS, VSD, VOR, VOR3, VOR4, UOP, PCT, PS, PDF) diff --git a/src/main/resources/templates/convert/file-to-pdf.html b/src/main/resources/templates/convert/file-to-pdf.html index 26217b56..c0553c26 100644 --- a/src/main/resources/templates/convert/file-to-pdf.html +++ b/src/main/resources/templates/convert/file-to-pdf.html @@ -22,7 +22,17 @@

-

+

Microsoft Word: (DOC, DOCX, DOT, DOTX)

+

Microsoft Excel: (CSV, XLS, XLSX, XLT, XLTX, SLK, DIF)

+

Microsoft PowerPoint: (PPT, PPTX)

+

OpenDocument Formats: (ODT, OTT, ODS, OTS, ODP, OTP, ODG, OTG)

+

Plain Text: (TXT, TEXT, XML)

+

Rich Text Format: (RTF)

+

Images: (BMP, GIF, JPEG, PNG, TIF, PBM, PGM, PPM, RAS, XBM, XPM, SVG, SVM, WMF)

+

HTML: (HTML)

+

Lotus Word Pro: (LWP)

+

StarOffice: (SDA, SDC, SDD, SDW, STC, STD, STI, STW, SXD, SXG, SXI, SXW)

+

Other: (DBF, FODS, VSD, VOR, VOR3, VOR4, UOP, PCT, PS, PDF)

https://help.libreoffice.org/latest/en-US/text/shared/guide/supported_formats.html diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index 4eaa22eb..f7d01c0e 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -22,8 +22,8 @@ - - +