book htmk

This commit is contained in:
Anthony Stirling 2024-02-09 23:24:25 +00:00
parent ca8519cb10
commit 15ad46fe1c
5 changed files with 45 additions and 166 deletions

View file

@ -41,32 +41,13 @@ public class PostStartupProcesses {
// Checking for DOCKER_INSTALL_BOOK_FORMATS environment variable
if (bookFormatsInstalled) {
List<String> tmpList = new ArrayList<>();
// Set up the timezone configuration commands
tmpList.addAll(
Arrays.asList(
"sh",
"-c",
"echo 'tzdata tzdata/Areas select Europe' | debconf-set-selections; "
+ "echo 'tzdata tzdata/Zones/Europe select Berlin' | debconf-set-selections"));
commands.add(tmpList);
// Install calibre with DEBIAN_FRONTEND set to noninteractive
tmpList = new ArrayList<>();
tmpList.addAll(
Arrays.asList(
"sh",
"-c",
"DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends calibre"));
tmpList.addAll(Arrays.asList("whoami"));
commands.add(tmpList);
}
// Checking for DOCKER_INSTALL_HTML_FORMATS environment variable
if (htmlFormatsInstalled) {
List<String> tmpList = new ArrayList<>();
// Add -y flag for automatic yes to prompts and --no-install-recommends to reduce size
tmpList.addAll(
Arrays.asList(
"apt-get", "install", "wkhtmltopdf", "-y", "--no-install-recommends"));
tmpList = new ArrayList<>();
tmpList.addAll(Arrays.asList("id"));
commands.add(tmpList);
}
@ -74,8 +55,6 @@ public class PostStartupProcesses {
// Run the command
if (runningInDocker) {
List<String> tmpList = new ArrayList<>();
tmpList.addAll(Arrays.asList("apt-get", "update"));
commands.add(0, tmpList);
for (List<String> list : commands) {
ProcessExecutorResult returnCode =

View file

@ -2,13 +2,18 @@ package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.apache.pdfbox.text.PDFTextStripper;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -17,6 +22,7 @@ import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest;
import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest;
import stirling.software.SPDF.model.api.converters.PdfToWordRequest;
import stirling.software.SPDF.utils.PDFToFile;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@RequestMapping("/api/v1/convert")
@ -59,9 +65,17 @@ public class ConvertPDFToOffice {
throws IOException, InterruptedException {
MultipartFile inputFile = request.getFileInput();
String outputFormat = request.getOutputFormat();
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
if ("txt".equals(request.getOutputFormat())) {
try (PDDocument document = Loader.loadPDF(inputFile.getBytes())) {
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(document);
return WebResponseUtils.bytesToWebResponse(text.getBytes(), Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ ".txt" , MediaType.TEXT_PLAIN);
}
} else {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
}
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf/word")

View file

@ -1,8 +1,9 @@
package stirling.software.SPDF.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@ -34,95 +35,40 @@ public class FileToPdf {
tempInputFile = Files.createTempFile("input_", ".html");
Files.write(tempInputFile, fileBytes);
} else {
tempInputFile = unzipAndGetMainHtml(fileBytes);
tempInputFile = Files.createTempFile("input_", ".zip");
Files.write(tempInputFile, fileBytes);
}
List<String> command = new ArrayList<>();
if (!htmlFormatsInstalled) {
command.add("weasyprint");
} else {
command.add("wkhtmltopdf");
command.add("--enable-local-file-access");
command.add("--load-error-handling");
command.add("ignore");
command.add("--load-media-error-handling");
command.add("ignore");
command.add("--zoom");
command.add(String.valueOf(request.getZoom()));
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
} else {
command.add("ebook-convert");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
command.add("--paper-size");
command.add("a4");
// if custom zoom add zoom style direct to html
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/4900
if (request.getZoom() != 1.0) {
String htmlContent = new String(Files.readAllBytes(tempInputFile));
String zoomStyle = "<style>body { zoom: " + request.getZoom() + "; }</style>";
// Check for <head> tag, add style tag to associated tag
if (htmlContent.contains("<head>")) {
htmlContent = htmlContent.replace("<head>", "<head>" + zoomStyle);
} else if (htmlContent.contains("<html>")) {
// If no <head> tag, but <html> tag exists
htmlContent = htmlContent.replace("<html>", "<html>" + zoomStyle);
} else {
// If neither <head> nor <html> tags exist
htmlContent = zoomStyle + htmlContent;
// Create a temporary CSS file
File tempCssFile = File.createTempFile("customStyle", ".css");
try (FileWriter writer = new FileWriter(tempCssFile)) {
// Write the CSS rule to the file
writer.write("body { zoom: " + request.getZoom() + "; }");
}
// rewrite new html to file
Files.write(tempInputFile, htmlContent.getBytes(StandardCharsets.UTF_8));
}
if (request.getPageWidth() != null) {
command.add("--page-width");
command.add(request.getPageWidth() + "cm");
}
if (request.getPageHeight() != null) {
command.add("--page-height");
command.add(request.getPageHeight() + "cm");
}
if (request.getMarginTop() != null) {
command.add("--margin-top");
command.add(request.getMarginTop() + "mm");
}
// Repeat similar pattern for marginBottom, marginLeft, marginRight
if ("Yes".equalsIgnoreCase(request.getPrintBackground())) {
command.add("--background");
} else {
command.add("--no-background");
}
if ("Yes".equalsIgnoreCase(request.getDefaultHeader())) {
command.add("--default-header");
}
if ("print".equalsIgnoreCase(request.getCssMediaType())) {
command.add("--print-media-type");
} else if ("screen".equalsIgnoreCase(request.getCssMediaType())) {
command.add("--no-print-media-type");
command.add("--extra-css");
command.add(tempCssFile.getAbsolutePath());
}
}
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
ProcessExecutorResult returnCode;
if (fileName.endsWith(".zip")) {
if (htmlFormatsInstalled) {
// command.add(1, "--allow");
// command.add(2, tempInputFile.getParent().toString());
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(
command, tempInputFile.getParent().toFile());
} else {
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
pdfBytes = Files.readAllBytes(tempOutputFile);
} catch (IOException e) {
@ -135,10 +81,6 @@ public class FileToPdf {
// Clean up temporary files
Files.delete(tempOutputFile);
Files.delete(tempInputFile);
if (fileName.endsWith(".zip")) {
GeneralUtils.deleteDirectory(tempInputFile.getParent());
}
}
return pdfBytes;

View file

@ -20,63 +20,6 @@
<input type="number" step="0.1" class="form-control" id="zoom" name="zoom" value="1" />
</div>
<div class="mb-3">
<label for="pageWidth" th:text="#{HTMLToPDF.pageWidth}" class="form-label"></label>
<input type="number" class="form-control" id="pageWidth" name="pageWidth" />
</div>
<div class="mb-3">
<label for="pageHeight" th:text="#{HTMLToPDF.pageHeight}" class="form-label"></label>
<input type="number" class="form-control" id="pageHeight" name="pageHeight" />
</div>
<div class="mb-3">
<label for="marginTop" th:text="#{HTMLToPDF.marginTop}" class="form-label"></label>
<input type="number" class="form-control" id="marginTop" name="marginTop" />
</div>
<div class="mb-3">
<label for="marginBottom" th:text="#{HTMLToPDF.marginBottom}" class="form-label"></label>
<input type="number" class="form-control" id="marginBottom" name="marginBottom" />
</div>
<div class="mb-3">
<label for="marginLeft" th:text="#{HTMLToPDF.marginLeft}" class="form-label"></label>
<input type="number" class="form-control" id="marginLeft" name="marginLeft" />
</div>
<div class="mb-3">
<label for="marginRight" th:text="#{HTMLToPDF.marginRight}" class="form-label"></label>
<input type="number" class="form-control" id="marginRight" name="marginRight" />
</div>
<div class="mb-3">
<label th:text="#{HTMLToPDF.printBackground}" class="form-label"></label>
<select class="form-select" name="printBackground">
<option value="Yes" th:text="#{yes}">Yes</option>
<option value="No" th:text="#{no}">No</option>
</select>
</div>
<div class="mb-3">
<label th:text="#{HTMLToPDF.defaultHeader}" class="form-label"></label>
<select class="form-select" name="defaultHeader">
<option value="No" th:text="#{no}">No</option>
<option value="Yes" th:text="#{yes}">Yes</option>
</select>
</div>
<div class="mb-3">
<label th:text="#{HTMLToPDF.cssMediaType}" class="form-label"></label>
<select class="form-select" name="cssMediaType">
<option value="screen" th:text="#{HTMLToPDF.screen}">Screen</option>
<option value="none" th:text="#{HTMLToPDF.none}">None</option>
<option value="print" th:text="#{HTMLToPDF.print}">Print</option>
</select>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{HTMLToPDF.submit}"></button>

View file

@ -19,6 +19,7 @@
<label th:text="#{PDFToText.selectText.1}"></label>
<select class="form-control" name="outputFormat">
<option value="rtf">RTF</option>
<option value="txt">TXT</option>
</select>
</div>
<br>