mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 11:23:10 +02:00
feat(cbz-to-pdf,pdf-to-cbz): Converter for CBZ format to and from PDF (#4472)
This commit is contained in:
+86
-1
@@ -8,6 +8,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@@ -16,6 +17,7 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
@@ -30,11 +32,22 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.model.api.converters.ConvertCbzToPdfRequest;
|
||||
import stirling.software.SPDF.model.api.converters.ConvertPdfToCbzRequest;
|
||||
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
|
||||
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.*;
|
||||
import stirling.software.common.util.CbzUtils;
|
||||
import stirling.software.common.util.CheckProgramInstall;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
import stirling.software.common.util.PdfToCbzUtils;
|
||||
import stirling.software.common.util.PdfUtils;
|
||||
import stirling.software.common.util.ProcessExecutor;
|
||||
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.common.util.RegexPatternUtils;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/convert")
|
||||
@@ -44,6 +57,10 @@ import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
||||
public class ConvertImgPDFController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
private static final Pattern EXTENSION_PATTERN =
|
||||
RegexPatternUtils.getInstance().getPattern(RegexPatternUtils.getExtensionRegex());
|
||||
private static final String DEFAULT_COMIC_NAME = "comic";
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/img")
|
||||
@Operation(
|
||||
@@ -234,6 +251,74 @@ public class ConvertImgPDFController {
|
||||
GeneralUtils.generateFilename(file[0].getOriginalFilename(), "_converted.pdf"));
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/cbz/pdf")
|
||||
@Operation(
|
||||
summary = "Convert CBZ comic book archive to PDF",
|
||||
description =
|
||||
"This endpoint converts a CBZ (ZIP) comic book archive to a PDF file. "
|
||||
+ "Input:CBZ Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> convertCbzToPdf(@ModelAttribute ConvertCbzToPdfRequest request)
|
||||
throws IOException {
|
||||
MultipartFile file = request.getFileInput();
|
||||
byte[] pdfBytes;
|
||||
try {
|
||||
pdfBytes = CbzUtils.convertCbzToPdf(file, pdfDocumentFactory, tempFileManager);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String message = ex.getMessage() == null ? "Invalid CBZ file" : ex.getMessage();
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.body(message.getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
String filename = createConvertedFilename(file.getOriginalFilename(), "_converted.pdf");
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, filename);
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/cbz")
|
||||
@Operation(
|
||||
summary = "Convert PDF to CBZ comic book archive",
|
||||
description =
|
||||
"This endpoint converts a PDF file to a CBZ (ZIP) comic book archive. "
|
||||
+ "Input:PDF Output:CBZ Type:SISO")
|
||||
public ResponseEntity<byte[]> convertPdfToCbz(@ModelAttribute ConvertPdfToCbzRequest request)
|
||||
throws IOException {
|
||||
MultipartFile file = request.getFileInput();
|
||||
Integer dpi = request.getDpi();
|
||||
|
||||
if (dpi == null || dpi <= 0) {
|
||||
dpi = 300;
|
||||
}
|
||||
|
||||
byte[] cbzBytes;
|
||||
try {
|
||||
cbzBytes = PdfToCbzUtils.convertPdfToCbz(file, dpi, pdfDocumentFactory);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String message = ex.getMessage() == null ? "Invalid PDF file" : ex.getMessage();
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.contentType(MediaType.TEXT_PLAIN)
|
||||
.body(message.getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
String filename = createConvertedFilename(file.getOriginalFilename(), "_converted.cbz");
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
cbzBytes, filename, MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
private String createConvertedFilename(String originalFilename, String suffix) {
|
||||
if (originalFilename == null) {
|
||||
return GeneralUtils.generateFilename(DEFAULT_COMIC_NAME, suffix);
|
||||
}
|
||||
|
||||
String baseName = EXTENSION_PATTERN.matcher(originalFilename).replaceFirst("");
|
||||
if (baseName.isBlank()) {
|
||||
baseName = DEFAULT_COMIC_NAME;
|
||||
}
|
||||
|
||||
return GeneralUtils.generateFilename(baseName, suffix);
|
||||
}
|
||||
|
||||
private String getMediaType(String imageFormat) {
|
||||
String mimeType = URLConnection.guessContentTypeFromName("." + imageFormat);
|
||||
return "null".equals(mimeType) ? MediaType.APPLICATION_OCTET_STREAM_VALUE : mimeType;
|
||||
|
||||
+14
@@ -23,6 +23,20 @@ public class ConverterWebController {
|
||||
return "convert/img-to-pdf";
|
||||
}
|
||||
|
||||
@GetMapping("/cbz-to-pdf")
|
||||
@Hidden
|
||||
public String convertCbzToPdfForm(Model model) {
|
||||
model.addAttribute("currentPage", "cbz-to-pdf");
|
||||
return "convert/cbz-to-pdf";
|
||||
}
|
||||
|
||||
@GetMapping("/pdf-to-cbz")
|
||||
@Hidden
|
||||
public String convertPdfToCbzForm(Model model) {
|
||||
model.addAttribute("currentPage", "pdf-to-cbz");
|
||||
return "convert/pdf-to-cbz";
|
||||
}
|
||||
|
||||
@GetMapping("/html-to-pdf")
|
||||
@Hidden
|
||||
public String convertHTMLToPdfForm(Model model) {
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package stirling.software.SPDF.model.api.converters;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode
|
||||
public class ConvertCbzToPdfRequest {
|
||||
|
||||
@Schema(
|
||||
description = "The input CBZ file to be converted to a PDF file",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private MultipartFile fileInput;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package stirling.software.SPDF.model.api.converters;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode
|
||||
public class ConvertPdfToCbzRequest {
|
||||
|
||||
@Schema(
|
||||
description = "The input PDF file to be converted to a CBZ file",
|
||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private MultipartFile fileInput;
|
||||
|
||||
@Schema(
|
||||
description = "The DPI (Dots Per Inch) for rendering PDF pages as images",
|
||||
example = "300",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
||||
private Integer dpi = 300;
|
||||
}
|
||||
@@ -606,6 +606,14 @@ home.imageToPdf.title=Image to PDF
|
||||
home.imageToPdf.desc=Convert a image (PNG, JPEG, GIF, PSD) to PDF.
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo,psd,photoshop
|
||||
|
||||
home.cbzToPdf.title=CBZ to PDF
|
||||
home.cbzToPdf.desc=Convert CBZ comic book archives to PDF format.
|
||||
cbzToPdf.tags=conversion,comic,book,archive,cbz,zip
|
||||
|
||||
home.pdfToCbz.title=PDF to CBZ
|
||||
home.pdfToCbz.desc=Convert PDF files to CBZ comic book archives.
|
||||
pdfToCbz.tags=conversion,comic,book,archive,cbz,pdf
|
||||
|
||||
home.pdfToImage.title=PDF to Image
|
||||
home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF, PSD)
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo,psd,photoshop
|
||||
@@ -1431,6 +1439,18 @@ imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple
|
||||
imageToPDF.selectText.4=Merge into single PDF
|
||||
imageToPDF.selectText.5=Convert to separate PDFs
|
||||
|
||||
#cbzToPDF
|
||||
cbzToPDF.title=CBZ to PDF
|
||||
cbzToPDF.header=CBZ to PDF
|
||||
cbzToPDF.submit=Convert to PDF
|
||||
cbzToPDF.selectText=Select CBZ file
|
||||
|
||||
#pdfToCBZ
|
||||
pdfToCBZ.title=PDF to CBZ
|
||||
pdfToCBZ.header=PDF to CBZ
|
||||
pdfToCBZ.submit=Convert to CBZ
|
||||
pdfToCBZ.selectText=Select PDF file
|
||||
pdfToCBZ.dpi=DPI (Dots Per Inch)
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF to Image
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:data-language="${#locale.toString()}" th:dir="#{language.direction}" th:lang="${#locale.language}"
|
||||
xmlns:th="https://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{cbzToPDF.title}, header=#{cbzToPDF.header})}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon convertto">auto_stories</span>
|
||||
<span class="tool-header-text" th:text="#{cbzToPDF.header}"></span>
|
||||
</div>
|
||||
<form enctype="multipart/form-data" id="cbzToPDFForm" method="post"
|
||||
th:action="@{'/api/v1/convert/cbz/pdf'}">
|
||||
<div
|
||||
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='.cbz,.zip', inputText=#{cbzToPDF.selectText})}">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<button class="btn btn-primary" id="submitBtn" th:text="#{cbzToPDF.submit}" type="submit">Convert to PDF</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:data-language="${#locale.toString()}" th:dir="#{language.direction}" th:lang="${#locale.language}"
|
||||
xmlns:th="https://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{pdfToCBZ.title}, header=#{pdfToCBZ.header})}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon convert">auto_stories</span>
|
||||
<span class="tool-header-text" th:text="#{pdfToCBZ.header}"></span>
|
||||
</div>
|
||||
<form enctype="multipart/form-data" id="pdfToCBZForm" method="post"
|
||||
th:action="@{'/api/v1/convert/pdf/cbz'}">
|
||||
<div
|
||||
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf', inputText=#{pdfToCBZ.selectText})}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dpi" th:text="#{pdfToCBZ.dpi}">DPI:</label>
|
||||
<input class="form-control" id="dpi" max="600" min="72" name="dpi" required step="1" type="number" value="300">
|
||||
</div>
|
||||
<br>
|
||||
<button class="btn btn-primary" id="submitBtn" th:text="#{pdfToCBZ.submit}" type="submit">Convert to CBZ</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -47,6 +47,9 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('cbz-to-pdf', 'auto_stories', 'home.cbzToPdf.title', 'home.cbzToPdf.desc', 'cbzToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('file-to-pdf', 'draft', 'home.fileToPDF.title', 'home.fileToPDF.desc', 'fileToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
@@ -71,6 +74,9 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-cbz', 'auto_stories', 'home.pdfToCbz.title', 'home.pdfToCbz.desc', 'pdfToCbz.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-pdfa', 'picture_as_pdf', 'home.pdfToPDFA.title', 'home.pdfToPDFA.desc', 'pdfToPDFA.tags', 'convert')}">
|
||||
</div>
|
||||
@@ -98,13 +104,16 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="convertGroup" class="feature-group">
|
||||
<div class="feature-group" id="convertGroup">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('cbz-to-pdf', 'auto_stories', 'home.cbzToPdf.title', 'home.cbzToPdf.desc', 'cbzToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('file-to-pdf', 'draft', 'home.fileToPDF.title', 'home.fileToPDF.desc', 'fileToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import stirling.software.common.util.CbzUtils;
|
||||
|
||||
class CbzUtilsTest {
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_ValidCbzFile() {
|
||||
MockMultipartFile cbzFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.cbz", "application/zip", "test content".getBytes());
|
||||
|
||||
assertTrue(CbzUtils.isCbzFile(cbzFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_ValidZipFile() {
|
||||
MockMultipartFile zipFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.zip", "application/zip", "test content".getBytes());
|
||||
|
||||
assertTrue(CbzUtils.isCbzFile(zipFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_InvalidFile() {
|
||||
MockMultipartFile textFile =
|
||||
new MockMultipartFile("file", "test.txt", "text/plain", "test content".getBytes());
|
||||
|
||||
assertFalse(CbzUtils.isCbzFile(textFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_NoFilename() {
|
||||
MockMultipartFile noNameFile =
|
||||
new MockMultipartFile("file", null, "application/zip", "test content".getBytes());
|
||||
|
||||
assertFalse(CbzUtils.isCbzFile(noNameFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_PdfFile() {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"file", "document.pdf", "application/pdf", "pdf content".getBytes());
|
||||
|
||||
assertFalse(CbzUtils.isCbzFile(pdfFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_JpegFile() {
|
||||
MockMultipartFile jpegFile =
|
||||
new MockMultipartFile("file", "image.jpg", "image/jpeg", "jpeg content".getBytes());
|
||||
|
||||
assertFalse(CbzUtils.isCbzFile(jpegFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_RarFile() {
|
||||
MockMultipartFile rarFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"archive.rar",
|
||||
"application/x-rar-compressed",
|
||||
"rar content".getBytes());
|
||||
|
||||
assertFalse(CbzUtils.isCbzFile(rarFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsCbzFile_MixedCaseExtension() {
|
||||
MockMultipartFile cbzFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.CBZ", "application/zip", "test content".getBytes());
|
||||
|
||||
assertTrue(CbzUtils.isCbzFile(cbzFile));
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.PdfToCbzUtils;
|
||||
|
||||
public class PdfToCbzUtilsTest {
|
||||
|
||||
@Mock private CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPdfFile() {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile("test", "test.pdf", "application/pdf", new byte[10]);
|
||||
MockMultipartFile nonPdfFile =
|
||||
new MockMultipartFile("test", "test.txt", "text/plain", new byte[10]);
|
||||
MockMultipartFile noNameFile =
|
||||
new MockMultipartFile("test", null, "application/pdf", new byte[10]);
|
||||
|
||||
Assertions.assertTrue(PdfToCbzUtils.isPdfFile(pdfFile));
|
||||
Assertions.assertFalse(PdfToCbzUtils.isPdfFile(nonPdfFile));
|
||||
Assertions.assertFalse(PdfToCbzUtils.isPdfFile(noNameFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertPdfToCbz_NullFile() {
|
||||
IllegalArgumentException exception =
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
PdfToCbzUtils.convertPdfToCbz(null, 300, pdfDocumentFactory);
|
||||
});
|
||||
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertPdfToCbz_EmptyFile() {
|
||||
MockMultipartFile emptyFile =
|
||||
new MockMultipartFile("test", "test.pdf", "application/pdf", new byte[0]);
|
||||
|
||||
IllegalArgumentException exception =
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
PdfToCbzUtils.convertPdfToCbz(emptyFile, 300, pdfDocumentFactory);
|
||||
});
|
||||
Assertions.assertEquals("File cannot be null or empty", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertPdfToCbz_NonPdfFile() {
|
||||
MockMultipartFile nonPdfFile =
|
||||
new MockMultipartFile("test", "test.txt", "text/plain", new byte[10]);
|
||||
|
||||
IllegalArgumentException exception =
|
||||
Assertions.assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
PdfToCbzUtils.convertPdfToCbz(nonPdfFile, 300, pdfDocumentFactory);
|
||||
});
|
||||
Assertions.assertEquals("File must be a PDF", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertPdfToCbz_ValidPdf() throws IOException {
|
||||
// Create a simple mock PDF
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile("test", "test.pdf", "application/pdf", new byte[100]);
|
||||
|
||||
// Mock the PDF document
|
||||
PDDocument mockDocument = Mockito.mock(PDDocument.class);
|
||||
Mockito.when(mockDocument.getNumberOfPages()).thenReturn(1);
|
||||
Mockito.when(pdfDocumentFactory.load(pdfFile)).thenReturn(mockDocument);
|
||||
|
||||
// structure
|
||||
Assertions.assertThrows(
|
||||
Exception.class,
|
||||
() -> {
|
||||
PdfToCbzUtils.convertPdfToCbz(pdfFile, 300, pdfDocumentFactory);
|
||||
});
|
||||
|
||||
// Verify that load was called
|
||||
Mockito.verify(pdfDocumentFactory).load(pdfFile);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user