diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEpubToPdf.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEpubToPdf.java new file mode 100644 index 00000000..6705bee8 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertEpubToPdf.java @@ -0,0 +1,139 @@ +package stirling.software.SPDF.controller.api.converters; + +import java.io.IOException; + +import org.commonmark.node.Node; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.utils.FileToPdf; +import stirling.software.SPDF.utils.WebResponseUtils; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.http.ResponseEntity; + +import io.swagger.v3.oas.annotations.Operation; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +@RestController +@Tag(name = "Convert", description = "Convert APIs") +public class ConvertEpubToPdf { + //TODO + @PostMapping(consumes = "multipart/form-data", value = "/epub-to-single-pdf") + @Hidden + @Operation( + summary = "Convert an EPUB file to a single PDF", + description = "This endpoint takes an EPUB file input and converts it to a single PDF." + ) + public ResponseEntity epubToSinglePdf( + @RequestPart(required = true, value = "fileInput") MultipartFile fileInput) + throws Exception { + + if (fileInput == null) { + throw new IllegalArgumentException("Please provide an EPUB file for conversion."); + } + + String originalFilename = fileInput.getOriginalFilename(); + if (originalFilename == null || !originalFilename.endsWith(".epub")) { + throw new IllegalArgumentException("File must be in .epub format."); + } + + Map epubContents = extractEpubContent(fileInput); + List htmlFilesOrder = getHtmlFilesOrderFromOpf(epubContents); + + List individualPdfs = new ArrayList<>(); + + for (String htmlFile : htmlFilesOrder) { + byte[] htmlContent = epubContents.get(htmlFile); + byte[] pdfBytes = FileToPdf.convertHtmlToPdf(htmlContent, htmlFile.replace(".html", ".pdf")); + individualPdfs.add(pdfBytes); + } + + // Pseudo-code to merge individual PDFs into one. + byte[] mergedPdfBytes = mergeMultiplePdfsIntoOne(individualPdfs); + + return WebResponseUtils.bytesToWebResponse(mergedPdfBytes, originalFilename.replace(".epub", ".pdf")); + } + + // Assuming a pseudo-code function that merges multiple PDFs into one. + private byte[] mergeMultiplePdfsIntoOne(List individualPdfs) { + // You can use a library such as iText or PDFBox to perform the merging here. + // Return the byte[] of the merged PDF. + return null; + } + + private Map extractEpubContent(MultipartFile fileInput) throws IOException { + Map contentMap = new HashMap<>(); + + try (ZipInputStream zis = new ZipInputStream(fileInput.getInputStream())) { + ZipEntry zipEntry = zis.getNextEntry(); + while (zipEntry != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int read = 0; + while ((read = zis.read(buffer)) != -1) { + baos.write(buffer, 0, read); + } + contentMap.put(zipEntry.getName(), baos.toByteArray()); + zipEntry = zis.getNextEntry(); + } + } + + return contentMap; + } + + private List getHtmlFilesOrderFromOpf(Map epubContents) throws Exception { + String opfContent = new String(epubContents.get("OEBPS/content.opf")); // Adjusting for given path + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(opfContent)); + Document doc = dBuilder.parse(is); + + NodeList itemRefs = doc.getElementsByTagName("itemref"); + List htmlFilesOrder = new ArrayList<>(); + + for (int i = 0; i < itemRefs.getLength(); i++) { + Element itemRef = (Element) itemRefs.item(i); + String idref = itemRef.getAttribute("idref"); + + NodeList items = doc.getElementsByTagName("item"); + for (int j = 0; j < items.getLength(); j++) { + Element item = (Element) items.item(j); + if (idref.equals(item.getAttribute("id"))) { + htmlFilesOrder.add(item.getAttribute("href")); // Fetching the actual href + break; + } + } + } + + return htmlFilesOrder; + } + + +} diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 5ae0c5a0..d66ed9c5 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -260,6 +260,37 @@ PdfToSinglePage.tags=single page # WEB PAGES # # # ########################### + + + +#pdfToSinglePage +pdfToSinglePage.title=PDF To Single Page +pdfToSinglePage.header=PDF To Single Page +pdfToSinglePage.submit=Convert To Single Page + + +#pageExtracter +pageExtracter.title=Extract Pages +pageExtracter.header=Extract Pages +pageExtracter.submit=Extract + + +#getPdfInfo +getPdfInfo.title=Get Info on PDF +getPdfInfo.header=Get Info on PDF +getPdfInfo.submit=Get Info +getPdfInfo.downloadJson=Download JSON + + +#markdown-to-pdf +MarkdownToPDF.title=Markdown To PDF +MarkdownToPDF.header=Markdown To PDF +MarkdownToPDF.submit=Convert +MarkdownToPDF.help=Work in progress +MarkdownToPDF.credit=Uses WeasyPrint + + + #url-to-pdf URLToPDF.title=URL To PDF URLToPDF.header=URL To PDF diff --git a/src/main/resources/templates/extract-page.html b/src/main/resources/templates/extract-page.html index 0a5fb158..9dd1b9ed 100644 --- a/src/main/resources/templates/extract-page.html +++ b/src/main/resources/templates/extract-page.html @@ -17,7 +17,7 @@
- +
diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index 5b4b594a..ef84ef3e 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -57,6 +57,8 @@
+
+
@@ -73,7 +75,7 @@
- +
@@ -102,6 +104,7 @@
+
diff --git a/src/main/resources/templates/pdf-to-single-page.html b/src/main/resources/templates/pdf-to-single-page.html index 1f5b64c6..75007224 100644 --- a/src/main/resources/templates/pdf-to-single-page.html +++ b/src/main/resources/templates/pdf-to-single-page.html @@ -14,7 +14,6 @@

-

diff --git a/src/main/resources/templates/security/get-info-on-pdf.html b/src/main/resources/templates/security/get-info-on-pdf.html index a77b5ae6..193056e4 100644 --- a/src/main/resources/templates/security/get-info-on-pdf.html +++ b/src/main/resources/templates/security/get-info-on-pdf.html @@ -1,35 +1,39 @@ - - - - - + + -
-
-
-

-
-
-
-

-

-

-
-
- +
+
+
+

+
+
+
+

+ +
+
+ - -
- -
- -
- - - Download JSON + +
+ +
+ +
+ + +
- -
-
-
+
+
+
-
-
-
+
+
+
\ No newline at end of file