mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-03 17:52:30 +02:00
chnages testing new stuff
This commit is contained in:
parent
585562b363
commit
ca1aa75208
22
build.gradle
22
build.gradle
@ -20,16 +20,26 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.27'
|
||||
//implementation 'org.apache.pdfbox:preflight:2.0.27'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
|
||||
implementation 'e-iceblue:spire.pdf.free:5.1.0'
|
||||
|
||||
implementation 'org.apache.poi:poi:5.2.3'
|
||||
implementation 'org.apache.poi:poi-ooxml:5.2.3'
|
||||
implementation 'org.apache.xmlgraphics:batik-transcoder:1.14'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
|
||||
|
||||
//general PDF
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.27'
|
||||
implementation 'com.itextpdf:itextpdf:5.5.13.3'
|
||||
|
||||
//xml conversions and others
|
||||
implementation 'org.apache.poi:poi:5.2.3'
|
||||
implementation 'org.apache.poi:poi-scratchpad:5.2.3'
|
||||
implementation 'org.apache.poi:poi-ooxml:5.2.3'
|
||||
implementation 'com.itextpdf.tool:xmlworker:5.5.13.3'
|
||||
|
||||
//docx conversions
|
||||
implementation('org.docx4j:docx4j:6.1.2') {
|
||||
exclude group: 'org.slf4j', module: 'slf4j-reload4j'
|
||||
}
|
||||
implementation 'org.docx4j:docx4j-export-fo:11.2.9'
|
||||
|
||||
}
|
||||
|
||||
jar {
|
||||
|
@ -9,6 +9,6 @@ public class AppConfig {
|
||||
@Bean(name = "appVersion")
|
||||
public String appVersion() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "Develop";
|
||||
return (version != null) ? version : "0.3.3";
|
||||
}
|
||||
}
|
@ -1,9 +1,23 @@
|
||||
package stirling.software.SPDF.controller;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -12,11 +26,9 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.spire.pdf.PdfCompressionLevel;
|
||||
import com.spire.pdf.PdfDocument;
|
||||
import com.spire.pdf.PdfPageBase;
|
||||
import com.spire.pdf.exporting.PdfImageInfo;
|
||||
import com.spire.pdf.graphics.PdfBitmap;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.pdf.PdfReader;
|
||||
import com.itextpdf.text.pdf.PdfStamper;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@ -32,36 +44,81 @@ public class CompressController {
|
||||
return "compress-pdf";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostMapping("/compress-pdf")
|
||||
public ResponseEntity<byte[]> compressPDF(@RequestParam("fileInput") MultipartFile pdfFile, @RequestParam("imageCompressionLevel") String imageCompressionLevel)
|
||||
throws IOException {
|
||||
// Load a sample PDF document
|
||||
PdfDocument document = new PdfDocument();
|
||||
document.loadFromBytes(pdfFile.getBytes());
|
||||
public ResponseEntity<byte[]> compressPDF(
|
||||
@RequestParam("fileInput") MultipartFile pdfFile,
|
||||
@RequestParam(value = "compressPDF", defaultValue = "false") boolean compressPDF,
|
||||
@RequestParam(value = "compressImages", defaultValue = "false") boolean compressImages,
|
||||
@RequestParam(value = "useLossyCompression", defaultValue = "false") boolean useLossyCompression,
|
||||
@RequestParam(value = "resolutionPercentage", defaultValue = "50") int resolutionPercentage) {
|
||||
|
||||
// Compress PDF
|
||||
document.getFileInfo().setIncrementalUpdate(false);
|
||||
document.setCompressionLevel(PdfCompressionLevel.Best);
|
||||
ByteArrayOutputStream baosPDFBox = new ByteArrayOutputStream();
|
||||
|
||||
try (InputStream is = pdfFile.getInputStream();
|
||||
PDDocument document = PDDocument.load(is)) {
|
||||
|
||||
// compress PDF Images
|
||||
for (int i = 0; i < document.getPages().getCount(); i++) {
|
||||
|
||||
PdfPageBase page = document.getPages().get(i);
|
||||
PdfImageInfo[] images = page.getImagesInfo();
|
||||
if (images != null && images.length > 0)
|
||||
for (int j = 0; j < images.length; j++) {
|
||||
PdfImageInfo image = images[j];
|
||||
PdfBitmap bp = new PdfBitmap(image.getImage());
|
||||
// bp.setPngDirectToJpeg(true);
|
||||
bp.setQuality(Integer.valueOf(imageCompressionLevel));
|
||||
|
||||
page.replaceImage(j, bp);
|
||||
if (compressImages) {
|
||||
for (PDPage page : document.getPages()) {
|
||||
PDResources resources = page.getResources();
|
||||
for (COSName cosName : resources.getXObjectNames()) {
|
||||
if (resources.isImageXObject(cosName)) {
|
||||
PDImageXObject image = (PDImageXObject) resources.getXObject(cosName);
|
||||
BufferedImage bufferedImage = image.getImage();
|
||||
BufferedImage resizedImage = resizeImage(bufferedImage, resolutionPercentage);
|
||||
|
||||
if (useLossyCompression) {
|
||||
File tempFile = File.createTempFile("pdfbox", ".jpg");
|
||||
ImageIO.write(resizedImage, "jpg", tempFile);
|
||||
PDImageXObject newImage = PDImageXObject.createFromFile(tempFile.getAbsolutePath(), document);
|
||||
resources.put(cosName, newImage);
|
||||
} else {
|
||||
File tempFile = File.createTempFile("pdfbox", ".png");
|
||||
ImageIO.write(resizedImage, "png", tempFile);
|
||||
PDImageXObject newImage = PDImageXObject.createFromFile(tempFile.getAbsolutePath(), document);
|
||||
resources.put(cosName, newImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.save(baosPDFBox);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_compressed.pdf");
|
||||
try (ByteArrayInputStream baisPDFBox = new ByteArrayInputStream(baosPDFBox.toByteArray());
|
||||
ByteArrayOutputStream baosFinal = new ByteArrayOutputStream()) {
|
||||
|
||||
PdfReader reader = new PdfReader(baisPDFBox);
|
||||
PdfStamper stamper = new PdfStamper(reader, baosFinal);
|
||||
|
||||
if (compressPDF) {
|
||||
stamper.setFullCompression();
|
||||
}
|
||||
|
||||
stamper.close();
|
||||
reader.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(baosFinal, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_compressed.pdf");
|
||||
} catch (IOException | DocumentException e) {
|
||||
e.printStackTrace();
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private BufferedImage resizeImage(BufferedImage originalImage, int resolutionPercentage) {
|
||||
int newWidth = originalImage.getWidth() * resolutionPercentage / 100;
|
||||
int newHeight = originalImage.getHeight() * resolutionPercentage / 100;
|
||||
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, originalImage.getType());
|
||||
Graphics2D g = resizedImage.createGraphics();
|
||||
g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
|
||||
g.dispose();
|
||||
return resizedImage;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
package stirling.software.SPDF.controller.converters;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.Paragraph;
|
||||
import com.itextpdf.text.pdf.PdfPCell;
|
||||
import com.itextpdf.text.pdf.PdfPTable;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@Controller
|
||||
public class ConvertCsvController {
|
||||
|
||||
|
||||
@GetMapping("/csv-to-pdf")
|
||||
public String cinvertToPDF(Model model) {
|
||||
model.addAttribute("currentPage", "xlsx-to-pdf");
|
||||
return "convert/xlsx-to-pdf";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostMapping("/csv-to-pdf")
|
||||
public ResponseEntity<byte[]> convertCsvToPdf(@RequestParam("fileInput") MultipartFile csvFile) throws IOException, DocumentException {
|
||||
// Create PDF document
|
||||
Document document = new Document();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
PdfWriter.getInstance(document, outputStream);
|
||||
document.open();
|
||||
|
||||
// Read CSV file
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(csvFile.getInputStream(), StandardCharsets.UTF_8);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
|
||||
|
||||
// Create PDF table from CSV content
|
||||
PdfPTable table = null;
|
||||
String csvRow;
|
||||
while ((csvRow = bufferedReader.readLine()) != null) {
|
||||
String[] csvRowCells = csvRow.split(","); // Assuming comma as a delimiter
|
||||
|
||||
if (table == null) {
|
||||
table = new PdfPTable(csvRowCells.length);
|
||||
}
|
||||
|
||||
for (String cellValue : csvRowCells) {
|
||||
PdfPCell pdfCell = new PdfPCell(new Paragraph(cellValue));
|
||||
table.addCell(pdfCell);
|
||||
}
|
||||
}
|
||||
|
||||
if (table != null) {
|
||||
document.add(table);
|
||||
}
|
||||
|
||||
// Close BufferedReader, document, and output stream
|
||||
bufferedReader.close();
|
||||
document.close();
|
||||
outputStream.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(outputStream, csvFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package stirling.software.SPDF.controller.converters;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.docx4j.Docx4J;
|
||||
import org.docx4j.openpackaging.exceptions.Docx4JException;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@Controller
|
||||
public class ConvertDocController {
|
||||
|
||||
|
||||
@GetMapping("/docx-to-pdf")
|
||||
public String cinvertToPDF(Model model) {
|
||||
model.addAttribute("currentPage", "xlsx-to-pdf");
|
||||
return "convert/xlsx-to-pdf";
|
||||
}
|
||||
|
||||
@PostMapping("/docx-to-pdf")
|
||||
public ResponseEntity<byte[]> convertDocxToPdf(@RequestParam("fileInput") MultipartFile docxFile) throws IOException, Docx4JException {
|
||||
// Load WordprocessingMLPackage
|
||||
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(docxFile.getInputStream());
|
||||
|
||||
// Create PDF output stream
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
// Convert DOCX to PDF
|
||||
Docx4J.toPDF(wordMLPackage, outputStream);
|
||||
|
||||
return PdfUtils.boasToWebResponse(outputStream, docxFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package stirling.software.SPDF.controller.converters;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
import com.itextpdf.tool.xml.XMLWorkerHelper;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@Controller
|
||||
public class ConvertHtmlController {
|
||||
|
||||
|
||||
@GetMapping("//html-to-pdf")
|
||||
public String cinvertToPDF(Model model) {
|
||||
model.addAttribute("currentPage", "xlsx-to-pdf");
|
||||
return "convert/xlsx-to-pdf";
|
||||
}
|
||||
|
||||
@PostMapping("/html-to-pdf")
|
||||
public ResponseEntity<byte[]> convertHtmlToPdf(@RequestParam("fileInput") MultipartFile htmlFile) throws IOException, DocumentException {
|
||||
// Create PDF document
|
||||
Document document = new Document();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
|
||||
document.open();
|
||||
|
||||
// Read HTML file
|
||||
InputStream htmlInputStream = new ByteArrayInputStream(htmlFile.getBytes());
|
||||
|
||||
// Convert HTML content to PDF
|
||||
XMLWorkerHelper.getInstance().parseXHtml(writer, document, htmlInputStream);
|
||||
|
||||
// Close document and output stream
|
||||
document.close();
|
||||
outputStream.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(outputStream, "");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package stirling.software.SPDF.controller.converters;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.Image;
|
||||
import com.itextpdf.text.PageSize;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@Controller
|
||||
public class ConvertPPTController {
|
||||
|
||||
|
||||
@GetMapping("/pptx-to-pdf")
|
||||
public String cinvertToPDF(Model model) {
|
||||
model.addAttribute("currentPage", "xlsx-to-pdf");
|
||||
return "convert/xlsx-to-pdf";
|
||||
}
|
||||
|
||||
@PostMapping("/pptx-to-pdf")
|
||||
public ResponseEntity<byte[]> convertPptxToPdf(@RequestParam("fileInput") MultipartFile pptxFile) throws IOException, DocumentException {
|
||||
// Read PowerPoint presentation
|
||||
XMLSlideShow ppt = new XMLSlideShow(pptxFile.getInputStream());
|
||||
|
||||
// Create PDF document
|
||||
Document pdfDocument = new Document(PageSize.A4.rotate());
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
PdfWriter.getInstance(pdfDocument, outputStream);
|
||||
pdfDocument.open();
|
||||
|
||||
// Convert PowerPoint slides to images, then add them to the PDF
|
||||
for (XSLFSlide slide : ppt.getSlides()) {
|
||||
BufferedImage slideImage = new BufferedImage((int) Math.ceil(ppt.getPageSize().getWidth()), (int) Math.ceil(ppt.getPageSize().getHeight()), BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = slideImage.createGraphics();
|
||||
|
||||
// Set graphics rendering hints for better quality
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
|
||||
// Draw the slide on the graphics
|
||||
graphics.setPaint(Color.white);
|
||||
graphics.fill(new Rectangle2D.Float(0, 0, slideImage.getWidth(), slideImage.getHeight()));
|
||||
slide.draw(graphics);
|
||||
|
||||
// Add the slide image to the PDF document
|
||||
Image image = Image.getInstance(slideImage, null);
|
||||
image.scaleToFit(PageSize.A4.getWidth() - 72, PageSize.A4.getHeight() - 72);
|
||||
pdfDocument.add(image);
|
||||
}
|
||||
|
||||
// Close PowerPoint and PDF documents
|
||||
ppt.close();
|
||||
pdfDocument.close();
|
||||
outputStream.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(outputStream, pptxFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package stirling.software.SPDF.controller.converters;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.Paragraph;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
|
||||
@Controller
|
||||
public class ConvertTextController {
|
||||
|
||||
|
||||
@GetMapping("/txt-rtf-to-pdf")
|
||||
public String cinvertToPDF(Model model) {
|
||||
model.addAttribute("currentPage", "xlsx-to-pdf");
|
||||
return "convert/xlsx-to-pdf";
|
||||
}
|
||||
|
||||
@PostMapping("/txt-rtf-to-pdf")
|
||||
public ResponseEntity<byte[]> convertTxtRtfToPdf(@RequestParam("fileInput") MultipartFile txtRtfFile) throws IOException, DocumentException {
|
||||
// Create PDF document
|
||||
Document document = new Document();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
PdfWriter.getInstance(document, outputStream);
|
||||
document.open();
|
||||
|
||||
// Read TXT/RTF file content
|
||||
String fileContent;
|
||||
String fileExtension = FilenameUtils.getExtension(txtRtfFile.getOriginalFilename());
|
||||
if (fileExtension.equalsIgnoreCase("rtf")) {
|
||||
HWPFDocument hwpfDocument = new HWPFDocument(new POIFSFileSystem(txtRtfFile.getInputStream()));
|
||||
fileContent = hwpfDocument.getText().toString();
|
||||
} else {
|
||||
fileContent = new String(txtRtfFile.getBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
// Add content to PDF
|
||||
document.add(new Paragraph(fileContent));
|
||||
|
||||
// Close document and output stream
|
||||
document.close();
|
||||
outputStream.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(outputStream, txtRtfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
}
|
@ -3,8 +3,15 @@ package stirling.software.SPDF.controller.converters;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFFont;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -16,6 +23,8 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import com.itextpdf.text.BaseColor;
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.Font;
|
||||
import com.itextpdf.text.Paragraph;
|
||||
import com.itextpdf.text.pdf.PdfPCell;
|
||||
import com.itextpdf.text.pdf.PdfPTable;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
@ -33,11 +42,10 @@ public class ConvertXlsxController {
|
||||
}
|
||||
|
||||
@PostMapping("/xlsx-to-pdf")
|
||||
public ResponseEntity<byte[]> convertToPDF(@RequestParam("fileInput") MultipartFile xlsx) throws IOException, DocumentException{
|
||||
// Load Excel file
|
||||
|
||||
public ResponseEntity<byte[]> convertToPDF(@RequestParam("fileInput") MultipartFile xlsx) throws IOException, DocumentException {
|
||||
// Load Excel file
|
||||
Workbook workbook = WorkbookFactory.create(xlsx.getInputStream());
|
||||
|
||||
|
||||
// Create PDF document
|
||||
Document document = new Document();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
@ -46,32 +54,99 @@ public class ConvertXlsxController {
|
||||
|
||||
// Convert each sheet in Excel to a separate page in PDF
|
||||
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
|
||||
PdfPTable table = new PdfPTable(workbook.getSheetAt(i).getRow(0).getPhysicalNumberOfCells());
|
||||
for (int row = 0; row < workbook.getSheetAt(i).getPhysicalNumberOfRows(); row++) {
|
||||
for (int cell = 0; cell < workbook.getSheetAt(i).getRow(row).getPhysicalNumberOfCells(); cell++) {
|
||||
PdfPCell pdfCell = new PdfPCell();
|
||||
pdfCell.addElement(new com.itextpdf.text.Paragraph(workbook.getSheetAt(i).getRow(row).getCell(cell).toString()));
|
||||
Sheet sheet = workbook.getSheetAt(i);
|
||||
int numOfColumns = sheet.getRow(0).getPhysicalNumberOfCells();
|
||||
PdfPTable table = new PdfPTable(numOfColumns);
|
||||
|
||||
// Copy cell style, borders, and background color
|
||||
pdfCell.setBorderColor(new BaseColor(workbook.getSheetAt(i).getRow(row).getCell(cell).getCellStyle().getBottomBorderColor()));
|
||||
pdfCell.setBorderColor(new BaseColor(workbook.getSheetAt(i).getRow(row).getCell(cell).getCellStyle().getTopBorderColor()));
|
||||
pdfCell.setBorderColor(new BaseColor(workbook.getSheetAt(i).getRow(row).getCell(cell).getCellStyle().getLeftBorderColor()));
|
||||
pdfCell.setBorderColor(new BaseColor(workbook.getSheetAt(i).getRow(row).getCell(cell).getCellStyle().getRightBorderColor()));
|
||||
Short bc = workbook.getSheetAt(i).getRow(row).getCell(cell).getCellStyle().getFillBackgroundColor();
|
||||
pdfCell.setBackgroundColor(new BaseColor(bc));
|
||||
for (int row = 0; row < sheet.getPhysicalNumberOfRows(); row++) {
|
||||
Row excelRow = sheet.getRow(row);
|
||||
if (excelRow == null) {
|
||||
continue; // Skip this row if it's null
|
||||
}
|
||||
for (int cell = 0; cell < excelRow.getPhysicalNumberOfCells(); cell++) {
|
||||
Cell excelCell = excelRow.getCell(cell);
|
||||
|
||||
// Check if the cell is null
|
||||
if (excelCell == null) {
|
||||
table.addCell(""); // Add an empty cell to the PDF table
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert cell to string
|
||||
DataFormatter dataFormatter = new DataFormatter();
|
||||
String cellValue = dataFormatter.formatCellValue(excelCell);
|
||||
System.out.println("Cell Value: " + cellValue);
|
||||
// Get Excel cell font
|
||||
Font cellFont = getFontFromExcelCell(workbook, excelCell);
|
||||
|
||||
// Create PDF cell with Excel cell font
|
||||
PdfPCell pdfCell = new PdfPCell(new Paragraph(cellValue, cellFont));
|
||||
|
||||
// Set cell height and width
|
||||
float height = sheet.getRow(row).getHeightInPoints();
|
||||
System.out.print(height);
|
||||
pdfCell.setFixedHeight(30f);
|
||||
|
||||
|
||||
// Copy cell style, borders, and background color
|
||||
XSSFCellStyle cellStyle = (XSSFCellStyle) excelCell.getCellStyle();
|
||||
if (cellStyle != null) {
|
||||
XSSFColor bottomBorderColor = cellStyle.getBottomBorderXSSFColor();
|
||||
if (bottomBorderColor != null) {
|
||||
pdfCell.setBorderColor(new BaseColor(bottomBorderColor.getRGB()[0] & 0xFF, bottomBorderColor.getRGB()[1] & 0xFF, bottomBorderColor.getRGB()[2] & 0xFF));
|
||||
}
|
||||
|
||||
XSSFColor topBorderColor = cellStyle.getTopBorderXSSFColor();
|
||||
if (topBorderColor != null) {
|
||||
pdfCell.setBorderColor(new BaseColor(topBorderColor.getRGB()[0] & 0xFF, topBorderColor.getRGB()[1] & 0xFF, topBorderColor.getRGB()[2] & 0xFF));
|
||||
}
|
||||
|
||||
XSSFColor leftBorderColor = cellStyle.getLeftBorderXSSFColor();
|
||||
if (leftBorderColor != null) {
|
||||
pdfCell.setBorderColor(new BaseColor(leftBorderColor.getRGB()[0] & 0xFF, leftBorderColor.getRGB()[1] & 0xFF, leftBorderColor.getRGB()[2] & 0xFF));
|
||||
}
|
||||
|
||||
XSSFColor rightBorderColor = cellStyle.getRightBorderXSSFColor();
|
||||
if (rightBorderColor != null) {
|
||||
pdfCell.setBorderColor(new BaseColor(rightBorderColor.getRGB()[0] & 0xFF, rightBorderColor.getRGB()[1] & 0xFF, rightBorderColor.getRGB()[2] & 0xFF));
|
||||
}
|
||||
|
||||
XSSFColor fillForegroundColor = cellStyle.getFillForegroundXSSFColor();
|
||||
if (fillForegroundColor != null) {
|
||||
pdfCell.setBackgroundColor(new BaseColor(fillForegroundColor.getRGB()[0] & 0xFF, fillForegroundColor.getRGB()[1] & 0xFF, fillForegroundColor.getRGB()[2] & 0xFF));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
table.addCell(pdfCell);
|
||||
}
|
||||
}
|
||||
|
||||
// Add sheet to PDF
|
||||
document.add(table);
|
||||
|
||||
// Add page break if there are more sheets
|
||||
if (i < workbook.getNumberOfSheets() - 1) {
|
||||
document.newPage();
|
||||
}
|
||||
}
|
||||
|
||||
// Close document and output stream
|
||||
document.close();
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
return PdfUtils.boasToWebResponse(outputStream, xlsx.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
// Close document and input stream
|
||||
|
||||
outputStream.close();
|
||||
|
||||
// Return PDF as response
|
||||
return PdfUtils.boasToWebResponse(outputStream, xlsx.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_convertedToPDF.pdf");
|
||||
}
|
||||
|
||||
private Font getFontFromExcelCell(Workbook workbook, Cell excelCell) {
|
||||
XSSFFont excelFont = ((XSSFCellStyle) excelCell.getCellStyle()).getFont();
|
||||
Font.FontFamily fontFamily = Font.getFamily(excelFont.getFontName());
|
||||
float fontSize = excelFont.getFontHeightInPoints();
|
||||
int fontStyle = (excelFont.getBold() ? Font.BOLD : Font.NORMAL) | (excelFont.getItalic() ? Font.ITALIC : Font.NORMAL);
|
||||
|
||||
return new Font(fontFamily, fontSize, fontStyle);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,12 +2,19 @@ package stirling.software.SPDF.controller.security;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationMarkup;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -18,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WatermarkRemover;
|
||||
|
||||
@Controller
|
||||
public class WatermarkController {
|
||||
@ -28,6 +36,12 @@ public class WatermarkController {
|
||||
return "security/add-watermark";
|
||||
}
|
||||
|
||||
@GetMapping("/remove-watermark")
|
||||
public String removeWatermarkForm(Model model) {
|
||||
model.addAttribute("currentPage", "remove-watermark");
|
||||
return "security/remove-watermark";
|
||||
}
|
||||
|
||||
@PostMapping("/add-watermark")
|
||||
public ResponseEntity<byte[]> addWatermark(@RequestParam("fileInput") MultipartFile pdfFile, @RequestParam("watermarkText") String watermarkText,
|
||||
@RequestParam(defaultValue = "30", name = "fontSize") float fontSize, @RequestParam(defaultValue = "0", name = "rotation") float rotation,
|
||||
@ -71,4 +85,62 @@ public class WatermarkController {
|
||||
}
|
||||
return PdfUtils.pdfDocToWebResponse(document, pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping("/remove-watermark")
|
||||
public ResponseEntity<byte[]> removeWatermark(@RequestParam("fileInput") MultipartFile pdfFile, @RequestParam("watermarkText") String watermarkText) throws Exception {
|
||||
|
||||
// Load the input PDF
|
||||
PDDocument document = PDDocument.load(pdfFile.getInputStream());
|
||||
|
||||
// Create a new PDF document for the output
|
||||
PDDocument outputDocument = new PDDocument();
|
||||
|
||||
// Loop through the pages
|
||||
int numPages = document.getNumberOfPages();
|
||||
for (int i = 0; i < numPages; i++) {
|
||||
PDPage page = document.getPage(i);
|
||||
|
||||
// Process the content stream to remove the watermark text
|
||||
WatermarkRemover editor = new WatermarkRemover(watermarkText) {};
|
||||
editor.processPage(page);
|
||||
editor.processPage(page);
|
||||
// Add the page to the output document
|
||||
outputDocument.addPage(page);
|
||||
}
|
||||
|
||||
for (PDPage page : outputDocument.getPages()) {
|
||||
List<PDAnnotation> annotations = page.getAnnotations();
|
||||
List<PDAnnotation> annotationsToRemove = new ArrayList<>();
|
||||
|
||||
for (PDAnnotation annotation : annotations) {
|
||||
if (annotation instanceof PDAnnotationMarkup) {
|
||||
PDAnnotationMarkup markup = (PDAnnotationMarkup) annotation;
|
||||
String contents = markup.getContents();
|
||||
if (contents != null && contents.contains(watermarkText)) {
|
||||
annotationsToRemove.add(markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
annotations.removeAll(annotationsToRemove);
|
||||
}
|
||||
PDDocumentCatalog catalog = outputDocument.getDocumentCatalog();
|
||||
PDAcroForm acroForm = catalog.getAcroForm();
|
||||
if (acroForm != null) {
|
||||
List<PDField> fields = acroForm.getFields();
|
||||
for (PDField field : fields) {
|
||||
String fieldValue = field.getValueAsString();
|
||||
if (fieldValue.contains(watermarkText)) {
|
||||
field.setValue(fieldValue.replace(watermarkText, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PdfUtils.pdfDocToWebResponse(outputDocument, "removed.pdf");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import org.springframework.http.ResponseEntity;
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
import com.spire.pdf.PdfDocument;
|
||||
|
||||
public class PdfUtils {
|
||||
|
||||
@ -172,16 +171,7 @@ public class PdfUtils {
|
||||
return PdfUtils.boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> pdfDocToWebResponse(PdfDocument document, String docName) throws IOException {
|
||||
|
||||
// Open Byte Array and save document to it
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
document.saveToStream(baos);
|
||||
// Close the document
|
||||
document.close();
|
||||
|
||||
return PdfUtils.boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
|
||||
public static ResponseEntity<byte[]> pdfDocToWebResponse(PDDocument document, String docName) throws IOException {
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.pdfbox.contentstream.PDFStreamEngine;
|
||||
import org.apache.pdfbox.contentstream.operator.Operator;
|
||||
import org.apache.pdfbox.cos.COSArray;
|
||||
import org.apache.pdfbox.cos.COSBase;
|
||||
import org.apache.pdfbox.cos.COSString;
|
||||
|
||||
public class WatermarkRemover extends PDFStreamEngine {
|
||||
|
||||
private final String watermarkText;
|
||||
private final Pattern pattern;
|
||||
|
||||
public WatermarkRemover(String watermarkText) {
|
||||
this.watermarkText = watermarkText;
|
||||
this.pattern = Pattern.compile(Pattern.quote(watermarkText));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
|
||||
String operation = operator.getName();
|
||||
|
||||
boolean processText = false;
|
||||
if ("Tj".equals(operation) || "TJ".equals(operation) || "'".equals(operation) || "\"".equals(operation)) {
|
||||
processText = true;
|
||||
}
|
||||
|
||||
if (processText) {
|
||||
for(int j = 0 ; j < operands.size(); ++j) {
|
||||
COSBase operand = operands.get(j);
|
||||
if (operand instanceof COSString) {
|
||||
COSString cosString = (COSString) operand;
|
||||
String string = cosString.getString();
|
||||
Matcher matcher = pattern.matcher(string);
|
||||
if (matcher.find()) {
|
||||
string = matcher.replaceAll("");
|
||||
cosString.setValue(string.getBytes());
|
||||
}
|
||||
} else if (operand instanceof COSArray) {
|
||||
COSArray array = (COSArray) operand;
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
COSBase item = array.get(i);
|
||||
if (item instanceof COSString) {
|
||||
COSString cosString = (COSString) item;
|
||||
String string = cosString.getString();
|
||||
Matcher matcher = pattern.matcher(string);
|
||||
if (matcher.find()) {
|
||||
System.out.println("operation =" + operation);
|
||||
System.out.println("1 =" + string);
|
||||
string = matcher.replaceAll("");
|
||||
cosString.setValue(string.getBytes());
|
||||
array.set(i, cosString);
|
||||
operands.set(j, array);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
super.processOperator(operator, operands);
|
||||
}
|
||||
}
|
@ -14,15 +14,61 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 th:text="#{compress.header}"></h2>
|
||||
<form action="#" th:action="@{compress-pdf}" th:object="${rotateForm}" method="post" enctype="multipart/form-data">
|
||||
<p th:text="#{processTimeWarning}"></p>
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
||||
<div class="form-group">
|
||||
<label for="imageCompressionLevel" th:text="#{compress.compressLevel}"></label>
|
||||
<input type="number" class="form-control" id="imageCompressionLevel" name="imageCompressionLevel" step="1" value="1" min="1" max="100" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{compress.submit}"></button>
|
||||
</form>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{/compress-pdf}">
|
||||
<div class="form-group">
|
||||
<label for="fileInput">Select a PDF file to compress:</label>
|
||||
<input type="file" class="form-control-file" id="fileInput" name="fileInput" accept=".pdf">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="compressPDF" name="compressPDF" checked>
|
||||
<label class="form-check-label" for="compressPDF">Compress PDF?</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pdfCompressionLevel">PDF Compression Level:</label>
|
||||
<select class="form-control" id="pdfCompressionLevel" name="pdfCompressionLevel">
|
||||
<option value="0">0 (No compression)</option>
|
||||
<option value="1">1 (Lowest compression)</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5" selected>5 (Default compression)</option>
|
||||
<option value="6">6</option>
|
||||
<option value="7">7</option>
|
||||
<option value="8">8</option>
|
||||
<option value="9">9 (Maximum compression)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="compressImages" name="compressImages" checked>
|
||||
<label class="form-check-label" for="compressImages">Compress Images?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="useLossyCompression" name="useLossyCompression">
|
||||
<label class="form-check-label" for="useLossyCompression">Use Lossy Compression for Images?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="imageCompressionLevel">Image Compression Level:</label>
|
||||
<select class="form-control" id="imageCompressionLevel" name="imageCompressionLevel">
|
||||
<option value="0">0 (No compression)</option>
|
||||
<option value="10">10 (Lowest quality)</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50" selected>50 (Default quality)</option>
|
||||
<option value="75">75</option>
|
||||
<option value="90">90 (High quality)</option>
|
||||
<option value="100">100 (Best quality)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">Compress PDF</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<th:block th:insert="~{fragments/common :: filelist}"></th:block>
|
||||
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<th:block th:fragment="errorBanner">
|
||||
|
||||
<style>
|
||||
#github-button,
|
||||
#discord-button {
|
||||
@ -17,7 +18,7 @@
|
||||
background-color: #005b7f;
|
||||
}
|
||||
</style>
|
||||
<br th:if="${message}">
|
||||
<br th:if="${message}">
|
||||
<div id="errorContainer" th:if="${message}" class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<h4 class="alert-heading" th:text="'Error: ' + ${status} + ' ' + ${error}"></h4>
|
||||
<p th:text="${message} + ' for path: ' + ${path}"></p>
|
||||
@ -36,39 +37,53 @@
|
||||
<a href="https://discord.gg/Cn8pWhQRxZ" id="discord-button" target="_blank">Join our Discord server</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggletrace() {
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (traceDiv.style.maxHeight === "0px") {
|
||||
traceDiv.style.maxHeight = "500px";
|
||||
} else {
|
||||
traceDiv.style.maxHeight = "0px";
|
||||
<script>
|
||||
var traceVisible = false;
|
||||
|
||||
function toggletrace() {
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (!traceVisible) {
|
||||
traceDiv.style.maxHeight = "500px";
|
||||
traceVisible = true;
|
||||
} else {
|
||||
traceDiv.style.maxHeight = "0px";
|
||||
traceVisible = false;
|
||||
}
|
||||
adjustContainerHeight();
|
||||
}
|
||||
adjustContainerHeight();
|
||||
}
|
||||
|
||||
function copytrace() {
|
||||
var traceContent = document.getElementById("traceContent");
|
||||
var range = document.createRange();
|
||||
range.selectNode(traceContent);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
function copytrace() {
|
||||
var flip = false
|
||||
if(!traceVisible) {
|
||||
toggletrace()
|
||||
flip = true
|
||||
}
|
||||
var traceContent = document.getElementById("traceContent");
|
||||
var range = document.createRange();
|
||||
range.selectNode(traceContent);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
if(flip){
|
||||
toggletrace()
|
||||
}
|
||||
}
|
||||
|
||||
function dismissError() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "none";
|
||||
errorContainer.style.height ="0";
|
||||
}
|
||||
function dismissError() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
errorContainer.style.display = "none";
|
||||
errorContainer.style.height ="0";
|
||||
}
|
||||
|
||||
function adjustContainerHeight() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
var traceDiv = document.getElementById("trace");
|
||||
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
|
||||
}
|
||||
function adjustContainerHeight() {
|
||||
var errorContainer = document.getElementById("errorContainer");
|
||||
var traceDiv = document.getElementById("trace");
|
||||
if (traceVisible) {
|
||||
errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
|
||||
} else {
|
||||
errorContainer.style.height = "auto";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</th:block>
|
||||
</th:block>
|
@ -93,10 +93,12 @@ function compareVersions(version1, version2) {
|
||||
console.log("latestVersion=" + latestVersion)
|
||||
console.log("currentVersion=" + currentVersion)
|
||||
console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion))
|
||||
if (latestVersion != null && latestVersion != "" && compareVersions(currentVersion, latestVersion) > 0) {
|
||||
document.getElementById("update-btn").style.display = "block";
|
||||
if (latestVersion != null && latestVersion != "" && compareVersions(latestVersion, currentVersion) > 0) {
|
||||
document.getElementById("update-btn").style.visibility = "visible";
|
||||
console.log("visible")
|
||||
} else {
|
||||
document.getElementById("update-btn").style.display = "none";
|
||||
document.getElementById("update-btn").style.visibility = "hidden";
|
||||
console.log("hidden")
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,16 +168,12 @@ function compareVersions(version1, version2) {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-globe2" viewBox="0 0 20 20">
|
||||
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.539c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.312.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a13.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.694.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.418.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/>
|
||||
</svg>
|
||||
|
||||
|
||||
</a>
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="languageDropdown">
|
||||
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_US">English (US)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="en_GB">English (UK)</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="ar_AR">العربية</a>
|
||||
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="de_DE">Deutsch</a> <a class="dropdown-item lang_dropdown-item" href="" data-language-code="fr_FR">Français</a>
|
||||
</div></li>
|
||||
|
||||
<li class="nav-item">
|
||||
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<!-- Settings Button -->
|
||||
@ -201,6 +199,7 @@ function compareVersions(version1, version2) {
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary" id="update-btn">Update available</button>
|
||||
<div class="modal-body">
|
||||
<p th:text="'App Version: ' + ${@appVersion}"></p>
|
||||
<div class="form-group">
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div class="col-md-6">
|
||||
<h2 th:text="#{remove-watermark.header}"></h2>
|
||||
|
||||
<form method="post" enctype="multipart/form-data" action="remove-text">
|
||||
<form method="post" enctype="multipart/form-data" action="remove-watermark">
|
||||
<div class="form-group">
|
||||
<label th:text="#{remove-watermark.selectText.1}"></label>
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
||||
|
Loading…
Reference in New Issue
Block a user