mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-24 12:36:13 +00:00
Compare commits
No commits in common. "9b3e2c29a525093b60d14bc48bd877b014e80fda" and "dde6cc2d4940b55799271e1fa1f49f52779794f5" have entirely different histories.
9b3e2c29a5
...
dde6cc2d49
@ -3,7 +3,6 @@ package stirling.software.common.annotations;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@ -38,7 +37,7 @@ public @interface AutoJobPostMapping {
|
||||
|
||||
/** MIME types this endpoint accepts. Defaults to {@code multipart/form-data}. */
|
||||
@AliasFor(annotation = RequestMapping.class, attribute = "consumes")
|
||||
String[] consumes() default {MediaType.MULTIPART_FORM_DATA_VALUE};
|
||||
String[] consumes() default {"multipart/form-data"};
|
||||
|
||||
/**
|
||||
* Maximum execution time in milliseconds before the job is aborted. A negative value means "use
|
||||
|
@ -1,6 +1,5 @@
|
||||
package stirling.software.common.model.api;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@ -15,7 +14,7 @@ import lombok.NoArgsConstructor;
|
||||
public class PDFFile {
|
||||
@Schema(
|
||||
description = "The input PDF file",
|
||||
contentMediaType = MediaType.APPLICATION_PDF_VALUE,
|
||||
contentMediaType = "application/pdf",
|
||||
format = "binary")
|
||||
private MultipartFile fileInput;
|
||||
|
||||
|
@ -227,8 +227,7 @@ public class JobExecutorService {
|
||||
if (result instanceof byte[]) {
|
||||
// Store byte array directly to disk to avoid double memory consumption
|
||||
String fileId = fileStorage.storeBytes((byte[]) result, "result.pdf");
|
||||
taskManager.setFileResult(
|
||||
jobId, fileId, "result.pdf", MediaType.APPLICATION_PDF_VALUE);
|
||||
taskManager.setFileResult(jobId, fileId, "result.pdf", "application/pdf");
|
||||
log.debug("Stored byte[] result with fileId: {}", fileId);
|
||||
|
||||
// Let the byte array get collected naturally in the next GC cycle
|
||||
@ -240,7 +239,7 @@ public class JobExecutorService {
|
||||
if (body instanceof byte[]) {
|
||||
// Extract filename from content-disposition header if available
|
||||
String filename = "result.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
|
||||
if (response.getHeaders().getContentDisposition() != null) {
|
||||
String disposition =
|
||||
@ -277,7 +276,7 @@ public class JobExecutorService {
|
||||
if (fileId != null && !fileId.isEmpty()) {
|
||||
// Try to get filename and content type
|
||||
String filename = "result.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method getOriginalFileName =
|
||||
@ -318,7 +317,8 @@ public class JobExecutorService {
|
||||
// Store generic result
|
||||
taskManager.setResult(jobId, body);
|
||||
}
|
||||
} else if (result instanceof MultipartFile file) {
|
||||
} else if (result instanceof MultipartFile) {
|
||||
MultipartFile file = (MultipartFile) result;
|
||||
String fileId = fileStorage.storeFile(file);
|
||||
taskManager.setFileResult(
|
||||
jobId, fileId, file.getOriginalFilename(), file.getContentType());
|
||||
@ -335,7 +335,7 @@ public class JobExecutorService {
|
||||
if (fileId != null && !fileId.isEmpty()) {
|
||||
// Try to get filename and content type
|
||||
String filename = "result.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method getOriginalFileName =
|
||||
@ -398,8 +398,9 @@ public class JobExecutorService {
|
||||
HttpHeaders.CONTENT_DISPOSITION,
|
||||
"form-data; name=\"attachment\"; filename=\"result.pdf\"")
|
||||
.body(result);
|
||||
} else if (result instanceof MultipartFile file) {
|
||||
} else if (result instanceof MultipartFile) {
|
||||
// Return MultipartFile content
|
||||
MultipartFile file = (MultipartFile) result;
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(file.getContentType()))
|
||||
.header(
|
||||
|
@ -12,8 +12,6 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@ -30,8 +28,8 @@ public class EmlParser {
|
||||
Pattern.compile("=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=");
|
||||
|
||||
private static final String DISPOSITION_ATTACHMENT = "attachment";
|
||||
private static final String TEXT_PLAIN = MediaType.TEXT_PLAIN_VALUE;
|
||||
private static final String TEXT_HTML = MediaType.TEXT_HTML_VALUE;
|
||||
private static final String TEXT_PLAIN = "text/plain";
|
||||
private static final String TEXT_HTML = "text/html";
|
||||
private static final String MULTIPART_PREFIX = "multipart/";
|
||||
|
||||
private static final String HEADER_CONTENT_TYPE = "content-type:";
|
||||
@ -71,12 +69,12 @@ public class EmlParser {
|
||||
if (isJakartaMailAvailable()) {
|
||||
return extractEmailContentAdvanced(emlBytes, request, customHtmlSanitizer);
|
||||
} else {
|
||||
return extractEmailContentBasic(emlBytes, customHtmlSanitizer);
|
||||
return extractEmailContentBasic(emlBytes, request, customHtmlSanitizer);
|
||||
}
|
||||
}
|
||||
|
||||
private static EmailContent extractEmailContentBasic(
|
||||
byte[] emlBytes, CustomHtmlSanitizer customHtmlSanitizer) {
|
||||
byte[] emlBytes, EmlToPdfRequest request, CustomHtmlSanitizer customHtmlSanitizer) {
|
||||
String emlContent = new String(emlBytes, StandardCharsets.UTF_8);
|
||||
EmailContent content = new EmailContent();
|
||||
|
||||
@ -123,7 +121,7 @@ public class EmlParser {
|
||||
return extractFromMimeMessage(message, request, customHtmlSanitizer);
|
||||
|
||||
} catch (ReflectiveOperationException e) {
|
||||
return extractEmailContentBasic(emlBytes, customHtmlSanitizer);
|
||||
return extractEmailContentBasic(emlBytes, request, customHtmlSanitizer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@ import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import stirling.software.common.model.api.converters.EmlToPdfRequest;
|
||||
@ -35,10 +33,10 @@ public class EmlProcessingUtils {
|
||||
// MIME type detection
|
||||
private static final Map<String, String> EXTENSION_TO_MIME_TYPE =
|
||||
Map.of(
|
||||
".png", MediaType.IMAGE_PNG_VALUE,
|
||||
".jpg", MediaType.IMAGE_JPEG_VALUE,
|
||||
".jpeg", MediaType.IMAGE_JPEG_VALUE,
|
||||
".gif", MediaType.IMAGE_GIF_VALUE,
|
||||
".png", "image/png",
|
||||
".jpg", "image/jpeg",
|
||||
".jpeg", "image/jpeg",
|
||||
".gif", "image/gif",
|
||||
".bmp", "image/bmp",
|
||||
".webp", "image/webp",
|
||||
".svg", "image/svg+xml",
|
||||
@ -83,8 +81,8 @@ public class EmlProcessingUtils {
|
||||
|| lowerContent.contains("bcc:");
|
||||
boolean hasMimeStructure =
|
||||
lowerContent.contains("multipart/")
|
||||
|| lowerContent.contains(MediaType.TEXT_PLAIN_VALUE)
|
||||
|| lowerContent.contains(MediaType.TEXT_HTML_VALUE)
|
||||
|| lowerContent.contains("text/plain")
|
||||
|| lowerContent.contains("text/html")
|
||||
|| lowerContent.contains("boundary=");
|
||||
|
||||
int headerCount = 0;
|
||||
@ -466,7 +464,7 @@ public class EmlProcessingUtils {
|
||||
}
|
||||
}
|
||||
|
||||
return MediaType.IMAGE_PNG_VALUE; // Default MIME type
|
||||
return "image/png";
|
||||
}
|
||||
|
||||
public static String decodeUrlEncoded(String encoded) {
|
||||
|
@ -1,35 +0,0 @@
|
||||
package stirling.software.common.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.multipdf.PDFMergerUtility;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PDFService {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
/*
|
||||
* Merge multiple PDF documents into a single PDF document
|
||||
*
|
||||
* @param documents List of PDDocument to be merged
|
||||
* @return Merged PDDocument
|
||||
* @throws IOException If an error occurs during merging
|
||||
*/
|
||||
public PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
|
||||
PDDocument merged = pdfDocumentFactory.createNewDocument();
|
||||
PDFMergerUtility merger = new PDFMergerUtility();
|
||||
for (PDDocument doc : documents) {
|
||||
merger.appendDocument(merged, doc);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ public class PDFToFile {
|
||||
|
||||
public ResponseEntity<byte[]> processPdfToMarkdown(MultipartFile inputFile)
|
||||
throws IOException, InterruptedException {
|
||||
if (!MediaType.APPLICATION_PDF_VALUE.equals(inputFile.getContentType())) {
|
||||
if (!"application/pdf".equals(inputFile.getContentType())) {
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ public class PDFToFile {
|
||||
|
||||
public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
|
||||
throws IOException, InterruptedException {
|
||||
if (!MediaType.APPLICATION_PDF_VALUE.equals(inputFile.getContentType())) {
|
||||
if (!"application/pdf".equals(inputFile.getContentType())) {
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ public class PDFToFile {
|
||||
MultipartFile inputFile, String outputFormat, String libreOfficeFilter)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
if (!MediaType.APPLICATION_PDF_VALUE.equals(inputFile.getContentType())) {
|
||||
if (!"application/pdf".equals(inputFile.getContentType())) {
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import lombok.Data;
|
||||
@ -119,7 +118,7 @@ public class PdfAttachmentHandler {
|
||||
public String getContentType() {
|
||||
return attachment.getContentType() != null
|
||||
? attachment.getContentType()
|
||||
: MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
: "application/octet-stream";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
@ -157,8 +156,7 @@ public class PdfUtils {
|
||||
if (DPI > maxSafeDpi) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.dpiExceedsLimit",
|
||||
"DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause"
|
||||
+ " memory issues and crashes. Please use a lower DPI value.",
|
||||
"DPI value {0} exceeds maximum safe limit of {1}. High DPI values can cause memory issues and crashes. Please use a lower DPI value.",
|
||||
DPI,
|
||||
maxSafeDpi);
|
||||
}
|
||||
@ -198,9 +196,7 @@ public class PdfUtils {
|
||||
.contains("Maximum size of image exceeded")) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.pageTooBigForDpi",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please"
|
||||
+ " try a lower DPI value (recommended: 150 or"
|
||||
+ " less).",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).",
|
||||
i + 1,
|
||||
DPI);
|
||||
}
|
||||
@ -245,10 +241,7 @@ public class PdfUtils {
|
||||
.contains("Maximum size of image exceeded")) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.pageTooBigExceedsArray",
|
||||
"PDF page {0} is too large to render at {1} DPI. The"
|
||||
+ " resulting image would exceed Java's maximum"
|
||||
+ " array size. Please try a lower DPI value"
|
||||
+ " (recommended: 150 or less).",
|
||||
"PDF page {0} is too large to render at {1} DPI. The resulting image would exceed Java's maximum array size. Please try a lower DPI value (recommended: 150 or less).",
|
||||
i + 1,
|
||||
DPI);
|
||||
}
|
||||
@ -289,9 +282,7 @@ public class PdfUtils {
|
||||
.contains("Maximum size of image exceeded")) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.pageTooBigForDpi",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please"
|
||||
+ " try a lower DPI value (recommended: 150 or"
|
||||
+ " less).",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).",
|
||||
i + 1,
|
||||
DPI);
|
||||
}
|
||||
@ -324,8 +315,7 @@ public class PdfUtils {
|
||||
&& e.getMessage().contains("Maximum size of image exceeded")) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.pageTooBigForDpi",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please try"
|
||||
+ " a lower DPI value (recommended: 150 or less).",
|
||||
"PDF page {0} is too large to render at {1} DPI. Please try a lower DPI value (recommended: 150 or less).",
|
||||
i + 1,
|
||||
DPI);
|
||||
}
|
||||
@ -376,9 +366,7 @@ public class PdfUtils {
|
||||
&& e.getMessage().contains("Maximum size of image exceeded")) {
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.pageTooBigFor300Dpi",
|
||||
"PDF page {0} is too large to render at 300 DPI. The resulting image"
|
||||
+ " would exceed Java's maximum array size. Please use a lower DPI"
|
||||
+ " value for PDF-to-image conversion.",
|
||||
"PDF page {0} is too large to render at 300 DPI. The resulting image would exceed Java's maximum array size. Please use a lower DPI value for PDF-to-image conversion.",
|
||||
page + 1);
|
||||
}
|
||||
throw e;
|
||||
@ -447,7 +435,7 @@ public class PdfUtils {
|
||||
ImageProcessingUtils.convertColorType(image, colorType);
|
||||
// Use JPEGFactory if it's JPEG since JPEG is lossy
|
||||
PDImageXObject pdImage =
|
||||
(contentType != null && MediaType.IMAGE_JPEG_VALUE.equals(contentType))
|
||||
(contentType != null && "image/jpeg".equals(contentType))
|
||||
? JPEGFactory.createFromImage(doc, convertedImage)
|
||||
: LosslessFactory.createFromImage(doc, convertedImage);
|
||||
addImageToDocument(doc, pdImage, fitOption, autoRotate);
|
||||
|
@ -4,8 +4,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@ -13,13 +11,9 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class WebResponseUtils {
|
||||
|
||||
public static ResponseEntity<byte[]> baosToWebResponse(
|
||||
@ -70,59 +64,4 @@ public class WebResponseUtils {
|
||||
|
||||
return baosToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a File to a web response (PDF default).
|
||||
*
|
||||
* @param outputTempFile The temporary file to be sent as a response.
|
||||
* @param docName The name of the document.
|
||||
* @return A ResponseEntity containing the file as a resource.
|
||||
*/
|
||||
public static ResponseEntity<StreamingResponseBody> pdfFileToWebResponse(
|
||||
TempFile outputTempFile, String docName) throws IOException {
|
||||
return fileToWebResponse(outputTempFile, docName, MediaType.APPLICATION_PDF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a File to a web response (ZIP default).
|
||||
*
|
||||
* @param outputTempFile The temporary file to be sent as a response.
|
||||
* @param docName The name of the document.
|
||||
* @return A ResponseEntity containing the file as a resource.
|
||||
*/
|
||||
public static ResponseEntity<StreamingResponseBody> zipFileToWebResponse(
|
||||
TempFile outputTempFile, String docName) throws IOException {
|
||||
return fileToWebResponse(outputTempFile, docName, MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a File to a web response with explicit media type (e.g., ZIP).
|
||||
*
|
||||
* @param outputTempFile The temporary file to be sent as a response.
|
||||
* @param docName The name of the document.
|
||||
* @param mediaType The content type to set on the response.
|
||||
* @return A ResponseEntity containing the file as a resource.
|
||||
*/
|
||||
public static ResponseEntity<StreamingResponseBody> fileToWebResponse(
|
||||
TempFile outputTempFile, String docName, MediaType mediaType) throws IOException {
|
||||
|
||||
Path path = outputTempFile.getFile().toPath().normalize();
|
||||
long len = Files.size(path);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(mediaType);
|
||||
headers.setContentLength(len);
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + docName + "\"");
|
||||
|
||||
StreamingResponseBody body =
|
||||
os -> {
|
||||
try (os) {
|
||||
Files.copy(path, os);
|
||||
os.flush();
|
||||
} finally {
|
||||
outputTempFile.close();
|
||||
}
|
||||
};
|
||||
|
||||
return new ResponseEntity<>(body, headers, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
@ -24,7 +23,7 @@ class ApplicationPropertiesSaml2HttpTest {
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setResponseCode(200)
|
||||
.addHeader("Content-Type", MediaType.APPLICATION_XML_VALUE)
|
||||
.addHeader("Content-Type", "application/xml")
|
||||
.setBody("<EntityDescriptor/>"));
|
||||
server.start();
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
package stirling.software.common.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static stirling.software.common.service.SpyPDFDocumentFactory.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
@ -18,11 +18,9 @@ import org.junit.jupiter.api.parallel.Execution;
|
||||
import org.junit.jupiter.api.parallel.ExecutionMode;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import stirling.software.common.model.api.PDFFile;
|
||||
import stirling.software.common.service.SpyPDFDocumentFactory.StrategyType;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@ -75,7 +73,7 @@ class CustomPDFDocumentFactoryTest {
|
||||
void testStrategy_MultipartFile(int sizeMB, StrategyType expected) throws IOException {
|
||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||
MockMultipartFile multipart =
|
||||
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
||||
new MockMultipartFile("file", "doc.pdf", "application/pdf", inflated);
|
||||
try (PDDocument doc = factory.load(multipart)) {
|
||||
Assertions.assertEquals(expected, factory.lastStrategyUsed);
|
||||
}
|
||||
@ -86,7 +84,7 @@ class CustomPDFDocumentFactoryTest {
|
||||
void testStrategy_PDFFile(int sizeMB, StrategyType expected) throws IOException {
|
||||
byte[] inflated = inflatePdf(basePdfBytes, sizeMB);
|
||||
MockMultipartFile multipart =
|
||||
new MockMultipartFile("file", "doc.pdf", MediaType.APPLICATION_PDF_VALUE, inflated);
|
||||
new MockMultipartFile("file", "doc.pdf", "application/pdf", inflated);
|
||||
PDFFile pdfFile = new PDFFile();
|
||||
pdfFile.setFileInput(multipart);
|
||||
try (PDDocument doc = factory.load(pdfFile)) {
|
||||
|
@ -2,8 +2,6 @@ package stirling.software.common.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.AdditionalAnswers.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -17,7 +15,6 @@ import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -39,7 +36,7 @@ class FileStorageTest {
|
||||
// Create a mock MultipartFile
|
||||
mockFile = mock(MultipartFile.class);
|
||||
when(mockFile.getOriginalFilename()).thenReturn("test.pdf");
|
||||
when(mockFile.getContentType()).thenReturn(MediaType.APPLICATION_PDF_VALUE);
|
||||
when(mockFile.getContentType()).thenReturn("application/pdf");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -13,7 +13,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import stirling.software.common.model.job.JobResult;
|
||||
@ -78,7 +77,7 @@ class TaskManagerTest {
|
||||
taskManager.createTask(jobId);
|
||||
String fileId = "file-id";
|
||||
String originalFileName = "test.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
long fileSize = 1024L;
|
||||
|
||||
// Mock the fileStorage.getFileSize() call
|
||||
@ -186,8 +185,7 @@ class TaskManagerTest {
|
||||
// 2. Create completed successful job with file
|
||||
String successFileJobId = "success-file-job";
|
||||
taskManager.createTask(successFileJobId);
|
||||
taskManager.setFileResult(
|
||||
successFileJobId, "file-id", "test.pdf", MediaType.APPLICATION_PDF_VALUE);
|
||||
taskManager.setFileResult(successFileJobId, "file-id", "test.pdf", "application/pdf");
|
||||
|
||||
// 3. Create completed successful job without file
|
||||
String successJobId = "success-job";
|
||||
@ -237,7 +235,7 @@ class TaskManagerTest {
|
||||
ResultFile.builder()
|
||||
.fileId("file-id")
|
||||
.fileName("test.pdf")
|
||||
.contentType(MediaType.APPLICATION_PDF_VALUE)
|
||||
.contentType("application/pdf")
|
||||
.fileSize(1024L)
|
||||
.build();
|
||||
ReflectionTestUtils.setField(oldJob, "resultFiles", java.util.List.of(resultFile));
|
||||
|
@ -25,7 +25,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -58,10 +57,7 @@ class PDFToFileTest {
|
||||
// Prepare
|
||||
MultipartFile nonPdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.txt",
|
||||
MediaType.TEXT_PLAIN_VALUE,
|
||||
"This is not a PDF".getBytes());
|
||||
"file", "test.txt", "text/plain", "This is not a PDF".getBytes());
|
||||
|
||||
// Execute
|
||||
ResponseEntity<byte[]> response = pdfToFile.processPdfToMarkdown(nonPdfFile);
|
||||
@ -75,10 +71,7 @@ class PDFToFileTest {
|
||||
// Prepare
|
||||
MultipartFile nonPdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.txt",
|
||||
MediaType.TEXT_PLAIN_VALUE,
|
||||
"This is not a PDF".getBytes());
|
||||
"file", "test.txt", "text/plain", "This is not a PDF".getBytes());
|
||||
|
||||
// Execute
|
||||
ResponseEntity<byte[]> response = pdfToFile.processPdfToHtml(nonPdfFile);
|
||||
@ -93,10 +86,7 @@ class PDFToFileTest {
|
||||
// Prepare
|
||||
MultipartFile nonPdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.txt",
|
||||
MediaType.TEXT_PLAIN_VALUE,
|
||||
"This is not a PDF".getBytes());
|
||||
"file", "test.txt", "text/plain", "This is not a PDF".getBytes());
|
||||
|
||||
// Execute
|
||||
ResponseEntity<byte[]> response =
|
||||
@ -112,10 +102,7 @@ class PDFToFileTest {
|
||||
// Prepare
|
||||
MultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"Fake PDF content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "Fake PDF content".getBytes());
|
||||
|
||||
// Execute with invalid format
|
||||
ResponseEntity<byte[]> response =
|
||||
@ -133,10 +120,7 @@ class PDFToFileTest {
|
||||
// Create a mock PDF file
|
||||
MultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"Fake PDF content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "Fake PDF content".getBytes());
|
||||
|
||||
// Create a mock HTML output file
|
||||
Path htmlOutputFile = tempDir.resolve("test.html");
|
||||
@ -184,7 +168,7 @@ class PDFToFileTest {
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"multipage.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"application/pdf",
|
||||
"Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
@ -261,10 +245,7 @@ class PDFToFileTest {
|
||||
// Create a mock PDF file
|
||||
MultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"Fake PDF content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
mockedStaticProcessExecutor
|
||||
@ -343,7 +324,7 @@ class PDFToFileTest {
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"document.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"application/pdf",
|
||||
"Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
@ -405,7 +386,7 @@ class PDFToFileTest {
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"document.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"application/pdf",
|
||||
"Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
@ -491,7 +472,7 @@ class PDFToFileTest {
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"document.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"application/pdf",
|
||||
"Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
@ -550,10 +531,7 @@ class PDFToFileTest {
|
||||
// Create a mock PDF file with no filename
|
||||
MultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"Fake PDF content".getBytes());
|
||||
"file", "", "application/pdf", "Fake PDF content".getBytes());
|
||||
|
||||
// Setup ProcessExecutor mock
|
||||
mockedStaticProcessExecutor
|
||||
|
@ -48,8 +48,7 @@ public class WebResponseUtilsTest {
|
||||
try {
|
||||
byte[] fileContent = "Sample file content".getBytes();
|
||||
MockMultipartFile file =
|
||||
new MockMultipartFile(
|
||||
"file", "sample.txt", MediaType.TEXT_PLAIN_VALUE, fileContent);
|
||||
new MockMultipartFile("file", "sample.txt", "text/plain", fileContent);
|
||||
|
||||
ResponseEntity<byte[]> responseEntity =
|
||||
WebResponseUtils.multiPartFileToWebResponse(file);
|
||||
|
@ -8,7 +8,6 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -25,10 +24,7 @@ class CustomColorReplaceStrategyTest {
|
||||
// Create a mock file
|
||||
mockFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"test pdf content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "test pdf content".getBytes());
|
||||
|
||||
// Initialize strategy with custom colors
|
||||
strategy =
|
||||
|
@ -24,7 +24,6 @@ import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -39,9 +38,7 @@ class InvertFullColorStrategyTest {
|
||||
void setUp() throws Exception {
|
||||
// Create a simple PDF document for testing
|
||||
byte[] pdfBytes = createSimplePdfWithRectangle();
|
||||
mockPdfFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
mockPdfFile = new MockMultipartFile("file", "test.pdf", "application/pdf", pdfBytes);
|
||||
|
||||
// Create the strategy instance
|
||||
strategy = new InvertFullColorStrategy(mockPdfFile, ReplaceAndInvert.FULL_INVERSION);
|
||||
|
@ -7,7 +7,6 @@ import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -36,10 +35,7 @@ class ReplaceAndInvertColorStrategyTest {
|
||||
// Arrange
|
||||
MultipartFile mockFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"test content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "test content".getBytes());
|
||||
ReplaceAndInvert replaceAndInvert = ReplaceAndInvert.CUSTOM_COLOR;
|
||||
|
||||
// Act
|
||||
@ -60,7 +56,7 @@ class ReplaceAndInvertColorStrategyTest {
|
||||
// Arrange
|
||||
byte[] content = "test pdf content".getBytes();
|
||||
MultipartFile mockFile =
|
||||
new MockMultipartFile("file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, content);
|
||||
new MockMultipartFile("file", "test.pdf", "application/pdf", content);
|
||||
ReplaceAndInvert replaceAndInvert = ReplaceAndInvert.CUSTOM_COLOR;
|
||||
|
||||
ReplaceAndInvertColorStrategy strategy =
|
||||
@ -78,16 +74,10 @@ class ReplaceAndInvertColorStrategyTest {
|
||||
// Arrange
|
||||
MultipartFile mockFile1 =
|
||||
new MockMultipartFile(
|
||||
"file1",
|
||||
"test1.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"content1".getBytes());
|
||||
"file1", "test1.pdf", "application/pdf", "content1".getBytes());
|
||||
MultipartFile mockFile2 =
|
||||
new MockMultipartFile(
|
||||
"file2",
|
||||
"test2.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"content2".getBytes());
|
||||
"file2", "test2.pdf", "application/pdf", "content2".getBytes());
|
||||
|
||||
// Act
|
||||
ReplaceAndInvertColorStrategy strategy =
|
||||
|
@ -11,7 +11,6 @@ import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.apache.pdfbox.pdmodel.encryption.PDEncryption;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -30,7 +29,7 @@ public class AnalysisController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/page-count", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/page-count", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get PDF page count",
|
||||
description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO")
|
||||
@ -40,7 +39,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/basic-info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/basic-info", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get basic PDF information",
|
||||
description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO")
|
||||
@ -54,7 +53,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/document-properties", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/document-properties", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get PDF document properties",
|
||||
description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO")
|
||||
@ -77,7 +76,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/page-dimensions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/page-dimensions", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get page dimensions for all pages",
|
||||
description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO")
|
||||
@ -97,7 +96,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/form-fields", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/form-fields", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get form field information",
|
||||
description =
|
||||
@ -120,7 +119,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/annotation-info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/annotation-info", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get annotation information",
|
||||
description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO")
|
||||
@ -144,7 +143,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/font-info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/font-info", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get font information",
|
||||
description =
|
||||
@ -166,7 +165,7 @@ public class AnalysisController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/security-info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/security-info", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Get security information",
|
||||
description =
|
||||
|
@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -34,7 +33,7 @@ public class CropController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/crop", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/crop", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Crops a PDF document",
|
||||
description =
|
||||
|
@ -46,7 +46,7 @@ public class EditTableOfContentsController {
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@PostMapping(value = "/extract-bookmarks", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Extract PDF Bookmarks",
|
||||
description = "Extracts bookmarks/table of contents from a PDF document as JSON.")
|
||||
@ -154,7 +154,7 @@ public class EditTableOfContentsController {
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/edit-table-of-contents", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Edit Table of Contents",
|
||||
description = "Add or edit bookmarks/table of contents in a PDF document.")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@ -19,14 +20,12 @@ import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlin
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||
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.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -37,9 +36,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.model.api.general.MergePdfsRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
import stirling.software.common.util.PdfErrorUtils;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@ -50,7 +48,6 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
public class MergeController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
// Merges a list of PDDocument objects into a single PDDocument
|
||||
public PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
|
||||
@ -65,54 +62,56 @@ public class MergeController {
|
||||
|
||||
// Returns a comparator for sorting MultipartFile arrays based on the given sort type
|
||||
private Comparator<MultipartFile> getSortComparator(String sortType) {
|
||||
return switch (sortType) {
|
||||
case "byFileName" -> Comparator.comparing(MultipartFile::getOriginalFilename);
|
||||
case "byDateModified" ->
|
||||
(file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file1.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file2.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
return attr1.lastModifiedTime().compareTo(attr2.lastModifiedTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byDateCreated" ->
|
||||
(file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file1.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file2.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
return attr1.creationTime().compareTo(attr2.creationTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byPDFTitle" ->
|
||||
(file1, file2) -> {
|
||||
try (PDDocument doc1 = pdfDocumentFactory.load(file1);
|
||||
PDDocument doc2 = pdfDocumentFactory.load(file2)) {
|
||||
String title1 = doc1.getDocumentInformation().getTitle();
|
||||
String title2 = doc2.getDocumentInformation().getTitle();
|
||||
return title1.compareTo(title2);
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
case "orderProvided" -> (file1, file2) -> 0; // Default is the order provided
|
||||
default -> (file1, file2) -> 0; // Default is the order provided
|
||||
};
|
||||
switch (sortType) {
|
||||
case "byFileName":
|
||||
return Comparator.comparing(MultipartFile::getOriginalFilename);
|
||||
case "byDateModified":
|
||||
return (file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file1.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file2.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
return attr1.lastModifiedTime().compareTo(attr2.lastModifiedTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byDateCreated":
|
||||
return (file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file1.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 =
|
||||
Files.readAttributes(
|
||||
Paths.get(file2.getOriginalFilename()),
|
||||
BasicFileAttributes.class);
|
||||
return attr1.creationTime().compareTo(attr2.creationTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byPDFTitle":
|
||||
return (file1, file2) -> {
|
||||
try (PDDocument doc1 = pdfDocumentFactory.load(file1);
|
||||
PDDocument doc2 = pdfDocumentFactory.load(file2)) {
|
||||
String title1 = doc1.getDocumentInformation().getTitle();
|
||||
String title2 = doc2.getDocumentInformation().getTitle();
|
||||
return title1.compareTo(title2);
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
case "orderProvided":
|
||||
default:
|
||||
return (file1, file2) -> 0; // Default is the order provided
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a table of contents to the merged document using filenames as chapter titles
|
||||
@ -155,18 +154,17 @@ public class MergeController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/merge-pdfs")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
|
||||
@Operation(
|
||||
summary = "Merge multiple PDF files into one",
|
||||
description =
|
||||
"This endpoint merges multiple PDF files into a single PDF file. The merged"
|
||||
+ " file will contain all pages from the input files in the order they were"
|
||||
+ " provided. Input:PDF Output:PDF Type:MISO")
|
||||
public ResponseEntity<StreamingResponseBody> mergePdfs(@ModelAttribute MergePdfsRequest request)
|
||||
public ResponseEntity<byte[]> mergePdfs(@ModelAttribute MergePdfsRequest request)
|
||||
throws IOException {
|
||||
List<File> filesToDelete = new ArrayList<>(); // List of temporary files to delete
|
||||
TempFile mergedTempFile = null;
|
||||
TempFile outputTempFile = null;
|
||||
File mergedTempFile = null;
|
||||
PDDocument mergedDocument = null;
|
||||
|
||||
boolean removeCertSign = Boolean.TRUE.equals(request.getRemoveCertSign());
|
||||
@ -184,14 +182,14 @@ public class MergeController {
|
||||
for (MultipartFile multipartFile : files) {
|
||||
totalSize += multipartFile.getSize();
|
||||
File tempFile =
|
||||
tempFileManager.convertMultipartFileToFile(
|
||||
GeneralUtils.convertMultipartFileToFile(
|
||||
multipartFile); // Convert MultipartFile to File
|
||||
filesToDelete.add(tempFile); // Add temp file to the list for later deletion
|
||||
mergerUtility.addSource(tempFile); // Add source file to the merger utility
|
||||
}
|
||||
|
||||
mergedTempFile = new TempFile(tempFileManager, ".pdf");
|
||||
mergerUtility.setDestinationFileName(mergedTempFile.getFile().getAbsolutePath());
|
||||
mergedTempFile = Files.createTempFile("merged-", ".pdf").toFile();
|
||||
mergerUtility.setDestinationFileName(mergedTempFile.getAbsolutePath());
|
||||
|
||||
try {
|
||||
mergerUtility.mergeDocuments(
|
||||
@ -206,7 +204,7 @@ public class MergeController {
|
||||
}
|
||||
|
||||
// Load the merged PDF document
|
||||
mergedDocument = pdfDocumentFactory.load(mergedTempFile.getFile());
|
||||
mergedDocument = pdfDocumentFactory.load(mergedTempFile);
|
||||
|
||||
// Remove signatures if removeCertSign is true
|
||||
if (removeCertSign) {
|
||||
@ -215,7 +213,7 @@ public class MergeController {
|
||||
if (acroForm != null) {
|
||||
List<PDField> fieldsToRemove =
|
||||
acroForm.getFields().stream()
|
||||
.filter(PDSignatureField.class::isInstance)
|
||||
.filter(field -> field instanceof PDSignatureField)
|
||||
.toList();
|
||||
|
||||
if (!fieldsToRemove.isEmpty()) {
|
||||
@ -231,15 +229,16 @@ public class MergeController {
|
||||
addTableOfContents(mergedDocument, files);
|
||||
}
|
||||
|
||||
// Save the modified document to a temporary file
|
||||
outputTempFile = new TempFile(tempFileManager, ".pdf");
|
||||
mergedDocument.save(outputTempFile.getFile());
|
||||
// Save the modified document to a new ByteArrayOutputStream
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mergedDocument.save(baos);
|
||||
|
||||
String mergedFileName =
|
||||
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "")
|
||||
+ "_merged_unsigned.pdf";
|
||||
return WebResponseUtils.pdfFileToWebResponse(
|
||||
outputTempFile, mergedFileName); // Return the modified PDF as stream
|
||||
return WebResponseUtils.baosToWebResponse(
|
||||
baos, mergedFileName); // Return the modified PDF
|
||||
|
||||
} catch (Exception ex) {
|
||||
if (ex instanceof IOException && PdfErrorUtils.isCorruptedPdfError((IOException) ex)) {
|
||||
log.warn("Corrupted PDF detected in merge pdf process: {}", ex.getMessage());
|
||||
@ -252,10 +251,12 @@ public class MergeController {
|
||||
mergedDocument.close(); // Close the merged document
|
||||
}
|
||||
for (File file : filesToDelete) {
|
||||
tempFileManager.deleteTempFile(file); // Delete temporary files
|
||||
if (file != null) {
|
||||
Files.deleteIfExists(file.toPath()); // Delete temporary files
|
||||
}
|
||||
}
|
||||
if (mergedTempFile != null) {
|
||||
mergedTempFile.close();
|
||||
Files.deleteIfExists(mergedTempFile.toPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -37,7 +36,7 @@ public class MultiPageLayoutController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/multi-page-layout", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/multi-page-layout", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Merge multiple pages of a PDF document into a single page",
|
||||
description =
|
||||
|
@ -4,7 +4,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
@ -47,7 +46,7 @@ public class PdfImageRemovalController {
|
||||
* content type and filename.
|
||||
* @throws IOException If an error occurs while processing the PDF file.
|
||||
*/
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/remove-image-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf")
|
||||
@Operation(
|
||||
summary = "Remove images from file to reduce the file size.",
|
||||
description =
|
||||
|
@ -39,7 +39,7 @@ public class PdfOverlayController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/overlay-pdfs", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Overlay PDF files in various modes",
|
||||
description =
|
||||
|
@ -7,7 +7,6 @@ import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -39,7 +38,7 @@ public class RearrangePagesPDFController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/remove-pages")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-pages")
|
||||
@Operation(
|
||||
summary = "Remove pages from a PDF file",
|
||||
description =
|
||||
@ -238,7 +237,7 @@ public class RearrangePagesPDFController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/rearrange-pages")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
|
||||
@Operation(
|
||||
summary = "Rearrange pages in a PDF file",
|
||||
description =
|
||||
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -32,7 +31,7 @@ public class RotationController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/rotate-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
|
||||
@Operation(
|
||||
summary = "Rotate a PDF file",
|
||||
description =
|
||||
|
@ -12,7 +12,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -39,7 +38,7 @@ public class ScalePagesController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/scale-pages", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/scale-pages", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Change the size of a PDF page/document",
|
||||
description =
|
||||
|
@ -30,8 +30,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@ -42,9 +40,8 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
public class SplitPDFController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/split-pages")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/split-pages")
|
||||
@Operation(
|
||||
summary = "Split a PDF file into separate documents",
|
||||
description =
|
||||
@ -58,11 +55,8 @@ public class SplitPDFController {
|
||||
PDDocument document = null;
|
||||
Path zipFile = null;
|
||||
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
||||
String filename;
|
||||
TempFile outputTempFile = null;
|
||||
|
||||
try {
|
||||
outputTempFile = new TempFile(tempFileManager, ".zip");
|
||||
|
||||
MultipartFile file = request.getFileInput();
|
||||
String pages = request.getPageNumbers();
|
||||
@ -111,11 +105,12 @@ public class SplitPDFController {
|
||||
// closing the original document
|
||||
document.close();
|
||||
|
||||
filename =
|
||||
zipFile = Files.createTempFile("split_documents", ".zip");
|
||||
|
||||
String filename =
|
||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||
.replaceFirst("[.][^.]+$", "");
|
||||
try (ZipOutputStream zipOut =
|
||||
new ZipOutputStream(Files.newOutputStream(outputTempFile.getPath()))) {
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
// loop through the split documents and write them to the zip file
|
||||
for (int i = 0; i < splitDocumentsBoas.size(); i++) {
|
||||
String fileName = filename + "_" + (i + 1) + ".pdf";
|
||||
@ -130,13 +125,19 @@ public class SplitPDFController {
|
||||
|
||||
log.debug("Wrote split document {} to zip file", fileName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed writing to zip", e);
|
||||
throw e;
|
||||
}
|
||||
log.debug(
|
||||
"Successfully created zip file with split documents: {}",
|
||||
outputTempFile.getPath());
|
||||
byte[] data = Files.readAllBytes(outputTempFile.getPath());
|
||||
|
||||
log.debug("Successfully created zip file with split documents: {}", zipFile.toString());
|
||||
byte[] data = Files.readAllBytes(zipFile);
|
||||
Files.deleteIfExists(zipFile);
|
||||
|
||||
// return the Resource in the response
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
|
||||
} finally {
|
||||
try {
|
||||
// Close the main document
|
||||
@ -151,9 +152,9 @@ public class SplitPDFController {
|
||||
}
|
||||
}
|
||||
|
||||
// Close the output temporary file
|
||||
if (outputTempFile != null) {
|
||||
outputTempFile.close();
|
||||
// Delete temporary zip file
|
||||
if (zipFile != null) {
|
||||
Files.deleteIfExists(zipFile);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error while cleaning up resources", e);
|
||||
|
@ -117,7 +117,7 @@ public class SplitPdfByChaptersController {
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/split-pdf-by-chapters", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Split PDFs by Chapters",
|
||||
description = "Splits a PDF into chapters and returns a ZIP file.")
|
||||
|
@ -2,8 +2,8 @@ package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
@ -17,13 +17,13 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
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.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -33,9 +33,6 @@ import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.PDFService;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@ -45,18 +42,16 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
public class SplitPdfBySectionsController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
private final PDFService pdfService;
|
||||
|
||||
@PostMapping(value = "/split-pdf-by-sections", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Split PDF pages into smaller sections",
|
||||
description =
|
||||
"Split each page of a PDF into smaller sections based on the user's choice"
|
||||
+ " (halves, thirds, quarters, etc.), both vertically and horizontally."
|
||||
+ " Input:PDF Output:ZIP-PDF Type:SISO")
|
||||
public ResponseEntity<StreamingResponseBody> splitPdf(
|
||||
@ModelAttribute SplitPdfBySectionsRequest request) throws Exception {
|
||||
public ResponseEntity<byte[]> splitPdf(@ModelAttribute SplitPdfBySectionsRequest request)
|
||||
throws Exception {
|
||||
List<ByteArrayOutputStream> splitDocumentsBoas = new ArrayList<>();
|
||||
|
||||
MultipartFile file = request.getFileInput();
|
||||
@ -72,14 +67,10 @@ public class SplitPdfBySectionsController {
|
||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||
.replaceFirst("[.][^.]+$", "");
|
||||
if (merge) {
|
||||
TempFile tempFile = new TempFile(tempFileManager, ".pdf");
|
||||
try (PDDocument merged = pdfService.mergeDocuments(splitDocuments);
|
||||
OutputStream out = Files.newOutputStream(tempFile.getPath())) {
|
||||
merged.save(out);
|
||||
for (PDDocument d : splitDocuments) d.close();
|
||||
sourceDocument.close();
|
||||
}
|
||||
return WebResponseUtils.pdfFileToWebResponse(tempFile, filename + "_split.pdf");
|
||||
MergeController mergeController = new MergeController(pdfDocumentFactory);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mergeController.mergeDocuments(splitDocuments).save(baos);
|
||||
return WebResponseUtils.bytesToWebResponse(baos.toByteArray(), filename + "_split.pdf");
|
||||
}
|
||||
for (PDDocument doc : splitDocuments) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@ -90,9 +81,10 @@ public class SplitPdfBySectionsController {
|
||||
|
||||
sourceDocument.close();
|
||||
|
||||
TempFile zipTempFile = new TempFile(tempFileManager, ".zip");
|
||||
try (ZipOutputStream zipOut =
|
||||
new ZipOutputStream(Files.newOutputStream(zipTempFile.getPath()))) {
|
||||
Path zipFile = Files.createTempFile("split_documents", ".zip");
|
||||
byte[] data;
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
int pageNum = 1;
|
||||
for (int i = 0; i < splitDocumentsBoas.size(); i++) {
|
||||
ByteArrayOutputStream baos = splitDocumentsBoas.get(i);
|
||||
@ -106,8 +98,15 @@ public class SplitPdfBySectionsController {
|
||||
|
||||
if (sectionNum == horiz * verti) pageNum++;
|
||||
}
|
||||
|
||||
zipOut.finish();
|
||||
data = Files.readAllBytes(zipFile);
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + "_split.zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
|
||||
} finally {
|
||||
Files.deleteIfExists(zipFile);
|
||||
}
|
||||
return WebResponseUtils.zipFileToWebResponse(zipTempFile, filename + "_split.zip");
|
||||
}
|
||||
|
||||
public List<PDDocument> splitPdfPages(
|
||||
|
@ -28,8 +28,6 @@ import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@ -40,9 +38,8 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
public class SplitPdfBySizeController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
@PostMapping(value = "/split-by-size-or-count", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Auto split PDF pages into separate documents based on size or count",
|
||||
description =
|
||||
@ -57,68 +54,89 @@ public class SplitPdfBySizeController {
|
||||
log.debug("Starting PDF split process with request: {}", request);
|
||||
MultipartFile file = request.getFileInput();
|
||||
|
||||
Path zipFile = Files.createTempFile("split_documents", ".zip");
|
||||
log.debug("Created temporary zip file: {}", zipFile);
|
||||
|
||||
String filename =
|
||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||
.replaceFirst("[.][^.]+$", "");
|
||||
log.debug("Base filename for output: {}", filename);
|
||||
|
||||
try (TempFile zipTempFile = new TempFile(tempFileManager, ".zip")) {
|
||||
Path zipFile = zipTempFile.getPath();
|
||||
log.debug("Created temporary zip file: {}", zipFile);
|
||||
try {
|
||||
log.debug("Reading input file bytes");
|
||||
byte[] pdfBytes = file.getBytes();
|
||||
log.debug("Successfully read {} bytes from input file", pdfBytes.length);
|
||||
byte[] data = null;
|
||||
try {
|
||||
log.debug("Reading input file bytes");
|
||||
byte[] pdfBytes = file.getBytes();
|
||||
log.debug("Successfully read {} bytes from input file", pdfBytes.length);
|
||||
|
||||
log.debug("Creating ZIP output stream");
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
log.debug("Loading PDF document");
|
||||
try (PDDocument sourceDocument = pdfDocumentFactory.load(pdfBytes)) {
|
||||
log.debug(
|
||||
"Successfully loaded PDF with {} pages",
|
||||
sourceDocument.getNumberOfPages());
|
||||
log.debug("Creating ZIP output stream");
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
log.debug("Loading PDF document");
|
||||
try (PDDocument sourceDocument = pdfDocumentFactory.load(pdfBytes)) {
|
||||
log.debug(
|
||||
"Successfully loaded PDF with {} pages",
|
||||
sourceDocument.getNumberOfPages());
|
||||
|
||||
int type = request.getSplitType();
|
||||
String value = request.getSplitValue();
|
||||
log.debug("Split type: {}, Split value: {}", type, value);
|
||||
int type = request.getSplitType();
|
||||
String value = request.getSplitValue();
|
||||
log.debug("Split type: {}, Split value: {}", type, value);
|
||||
|
||||
if (type == 0) {
|
||||
log.debug("Processing split by size");
|
||||
long maxBytes = GeneralUtils.convertSizeToBytes(value);
|
||||
log.debug("Max bytes per document: {}", maxBytes);
|
||||
handleSplitBySize(sourceDocument, maxBytes, zipOut, filename);
|
||||
} else if (type == 1) {
|
||||
log.debug("Processing split by page count");
|
||||
int pageCount = Integer.parseInt(value);
|
||||
log.debug("Pages per document: {}", pageCount);
|
||||
handleSplitByPageCount(sourceDocument, pageCount, zipOut, filename);
|
||||
} else if (type == 2) {
|
||||
log.debug("Processing split by document count");
|
||||
int documentCount = Integer.parseInt(value);
|
||||
log.debug("Total number of documents: {}", documentCount);
|
||||
handleSplitByDocCount(sourceDocument, documentCount, zipOut, filename);
|
||||
} else {
|
||||
log.error("Invalid split type: {}", type);
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.invalidArgument",
|
||||
"Invalid argument: {0}",
|
||||
"split type: " + type);
|
||||
}
|
||||
log.debug("PDF splitting completed successfully");
|
||||
if (type == 0) {
|
||||
log.debug("Processing split by size");
|
||||
long maxBytes = GeneralUtils.convertSizeToBytes(value);
|
||||
log.debug("Max bytes per document: {}", maxBytes);
|
||||
handleSplitBySize(sourceDocument, maxBytes, zipOut, filename);
|
||||
} else if (type == 1) {
|
||||
log.debug("Processing split by page count");
|
||||
int pageCount = Integer.parseInt(value);
|
||||
log.debug("Pages per document: {}", pageCount);
|
||||
handleSplitByPageCount(sourceDocument, pageCount, zipOut, filename);
|
||||
} else if (type == 2) {
|
||||
log.debug("Processing split by document count");
|
||||
int documentCount = Integer.parseInt(value);
|
||||
log.debug("Total number of documents: {}", documentCount);
|
||||
handleSplitByDocCount(sourceDocument, documentCount, zipOut, filename);
|
||||
} else {
|
||||
log.error("Invalid split type: {}", type);
|
||||
throw ExceptionUtils.createIllegalArgumentException(
|
||||
"error.invalidArgument",
|
||||
"Invalid argument: {0}",
|
||||
"split type: " + type);
|
||||
}
|
||||
|
||||
log.debug("PDF splitting completed successfully");
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.logException("PDF document loading or processing", e);
|
||||
throw e;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating or writing to ZIP file", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
byte[] data = Files.readAllBytes(zipFile);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.logException("PDF splitting process", e);
|
||||
throw e; // Re-throw to ensure proper error response
|
||||
} finally {
|
||||
try {
|
||||
log.debug("Reading ZIP file data");
|
||||
data = Files.readAllBytes(zipFile);
|
||||
log.debug("Successfully read {} bytes from ZIP file", data.length);
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading ZIP file data", e);
|
||||
}
|
||||
|
||||
log.debug("Returning response with {} bytes of data", data.length);
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
} catch (Exception e) {
|
||||
ExceptionUtils.logException("PDF splitting process", e);
|
||||
throw e; // Re-throw to ensure proper error response
|
||||
try {
|
||||
log.debug("Deleting temporary ZIP file");
|
||||
boolean deleted = Files.deleteIfExists(zipFile);
|
||||
log.debug("Temporary ZIP file deleted: {}", deleted);
|
||||
} catch (IOException e) {
|
||||
log.error("Error deleting temporary ZIP file", e);
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Returning response with {} bytes of data", data != null ? data.length : 0);
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
}
|
||||
|
||||
private void handleSplitBySize(
|
||||
|
@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -34,7 +33,7 @@ public class ToSinglePageController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf-to-single-page")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page")
|
||||
@Operation(
|
||||
summary = "Convert a multi-page PDF into a single long page PDF",
|
||||
description =
|
||||
|
@ -40,7 +40,7 @@ public class ConvertEmlToPDF {
|
||||
private final TempFileManager tempFileManager;
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/eml/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
|
||||
@Operation(
|
||||
summary = "Convert EML to PDF",
|
||||
description =
|
||||
|
@ -1,6 +1,5 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -37,7 +36,7 @@ public class ConvertHtmlToPDF {
|
||||
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/html/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
||||
@Operation(
|
||||
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
||||
description =
|
||||
|
@ -51,7 +51,7 @@ public class ConvertImgPDFController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/img")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/img")
|
||||
@Operation(
|
||||
summary = "Convert PDF to image(s)",
|
||||
description =
|
||||
@ -213,7 +213,7 @@ public class ConvertImgPDFController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/img/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/img/pdf")
|
||||
@Operation(
|
||||
summary = "Convert images to a PDF file",
|
||||
description =
|
||||
@ -244,7 +244,7 @@ public class ConvertImgPDFController {
|
||||
|
||||
private String getMediaType(String imageFormat) {
|
||||
String mimeType = URLConnection.guessContentTypeFromName("." + imageFormat);
|
||||
return "null".equals(mimeType) ? MediaType.APPLICATION_OCTET_STREAM_VALUE : mimeType;
|
||||
return "null".equals(mimeType) ? "application/octet-stream" : mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,7 +10,6 @@ import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.AttributeProvider;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -46,7 +45,7 @@ public class ConvertMarkdownToPdf {
|
||||
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/markdown/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a Markdown file to PDF",
|
||||
description =
|
||||
|
@ -12,7 +12,6 @@ import java.util.List;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
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;
|
||||
@ -172,7 +171,7 @@ public class ConvertOfficeController {
|
||||
return fileExtension.matches(extensionPattern);
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/file/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/file/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a file to a PDF using LibreOffice",
|
||||
description =
|
||||
|
@ -1,6 +1,5 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -19,7 +18,7 @@ import stirling.software.common.util.PDFToFile;
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertPDFToHtml {
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/html")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/html")
|
||||
@Operation(
|
||||
summary = "Convert PDF to HTML",
|
||||
description =
|
||||
|
@ -34,7 +34,7 @@ public class ConvertPDFToOffice {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/presentation")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/presentation")
|
||||
@Operation(
|
||||
summary = "Convert PDF to Presentation format",
|
||||
description =
|
||||
@ -49,7 +49,7 @@ public class ConvertPDFToOffice {
|
||||
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "impress_pdf_import");
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/text")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/text")
|
||||
@Operation(
|
||||
summary = "Convert PDF to Text or RTF format",
|
||||
description =
|
||||
@ -77,7 +77,7 @@ public class ConvertPDFToOffice {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/word")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/word")
|
||||
@Operation(
|
||||
summary = "Convert PDF to Word document",
|
||||
description =
|
||||
@ -91,7 +91,7 @@ public class ConvertPDFToOffice {
|
||||
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/xml")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/xml")
|
||||
@Operation(
|
||||
summary = "Convert PDF to XML",
|
||||
description =
|
||||
|
@ -78,7 +78,7 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertPDFToPDFA {
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/pdfa")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
|
||||
@Operation(
|
||||
summary = "Convert a PDF to a PDF/A",
|
||||
description =
|
||||
@ -89,7 +89,7 @@ public class ConvertPDFToPDFA {
|
||||
String outputFormat = request.getOutputFormat();
|
||||
|
||||
// Validate input file type
|
||||
if (!MediaType.APPLICATION_PDF_VALUE.equals(inputFile.getContentType())) {
|
||||
if (!"application/pdf".equals(inputFile.getContentType())) {
|
||||
log.error("Invalid input file type: {}", inputFile.getContentType());
|
||||
throw ExceptionUtils.createPdfFileRequiredException();
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -44,7 +43,7 @@ public class ConvertWebsiteToPDF {
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/url/pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/url/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a URL to a PDF",
|
||||
description =
|
||||
|
@ -46,7 +46,7 @@ public class ExtractCSVController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/pdf/csv", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/pdf/csv", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Extracts a CSV document from a PDF",
|
||||
description =
|
||||
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -38,7 +37,7 @@ public class FilterController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-contains-text")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-contains-text")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF contains set text, returns true if does",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
@ -56,7 +55,7 @@ public class FilterController {
|
||||
}
|
||||
|
||||
// TODO
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-contains-image")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-contains-image")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF contains an image",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
@ -72,7 +71,7 @@ public class FilterController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-page-count")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-count")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF is greater, less or equal to a setPageCount",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
@ -105,7 +104,7 @@ public class FilterController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-page-size")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-size")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF is of a certain size",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
@ -148,7 +147,7 @@ public class FilterController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-file-size")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-file-size")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF is a set file size",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
@ -181,7 +180,7 @@ public class FilterController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/filter-page-rotation")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation")
|
||||
@Operation(
|
||||
summary = "Checks if a PDF is of a certain rotation",
|
||||
description = "Input:PDF Output:Boolean Type:SISO")
|
||||
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
@ -35,7 +34,7 @@ public class AttachmentController {
|
||||
|
||||
private final AttachmentServiceInterface pdfAttachmentService;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/add-attachments")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-attachments")
|
||||
@Operation(
|
||||
summary = "Add attachments to PDF",
|
||||
description =
|
||||
|
@ -8,7 +8,6 @@ import java.util.List;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -39,7 +38,7 @@ public class AutoRenameController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/auto-rename")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/auto-rename")
|
||||
@Operation(
|
||||
summary = "Extract header from PDF file",
|
||||
description =
|
||||
|
@ -6,6 +6,7 @@ import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -35,8 +36,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@ -54,7 +53,6 @@ public class AutoSplitPdfController {
|
||||
"https://stirlingpdf.com"));
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
private static String decodeQRCode(BufferedImage bufferedImage) {
|
||||
LuminanceSource source;
|
||||
@ -104,7 +102,7 @@ public class AutoSplitPdfController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/auto-split-pdf", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Auto split PDF pages into separate documents",
|
||||
description =
|
||||
@ -119,10 +117,10 @@ public class AutoSplitPdfController {
|
||||
|
||||
PDDocument document = null;
|
||||
List<PDDocument> splitDocuments = new ArrayList<>();
|
||||
TempFile outputTempFile = null;
|
||||
Path zipFile = null;
|
||||
byte[] data = null;
|
||||
|
||||
try {
|
||||
outputTempFile = new TempFile(tempFileManager, ".zip");
|
||||
document = pdfDocumentFactory.load(file.getInputStream());
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
pdfRenderer.setSubsamplingAllowed(true);
|
||||
@ -154,12 +152,12 @@ public class AutoSplitPdfController {
|
||||
// Remove split documents that have no pages
|
||||
splitDocuments.removeIf(pdDocument -> pdDocument.getNumberOfPages() == 0);
|
||||
|
||||
zipFile = Files.createTempFile("split_documents", ".zip");
|
||||
String filename =
|
||||
Filenames.toSimpleFileName(file.getOriginalFilename())
|
||||
.replaceFirst("[.][^.]+$", "");
|
||||
|
||||
try (ZipOutputStream zipOut =
|
||||
new ZipOutputStream(Files.newOutputStream(outputTempFile.getPath()))) {
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
|
||||
for (int i = 0; i < splitDocuments.size(); i++) {
|
||||
String fileName = filename + "_" + (i + 1) + ".pdf";
|
||||
PDDocument splitDocument = splitDocuments.get(i);
|
||||
@ -175,10 +173,10 @@ public class AutoSplitPdfController {
|
||||
}
|
||||
}
|
||||
|
||||
byte[] data = Files.readAllBytes(outputTempFile.getPath());
|
||||
data = Files.readAllBytes(zipFile);
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error in auto split", e);
|
||||
throw e;
|
||||
@ -200,8 +198,12 @@ public class AutoSplitPdfController {
|
||||
}
|
||||
}
|
||||
|
||||
if (outputTempFile != null) {
|
||||
outputTempFile.close();
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
Files.deleteIfExists(zipFile);
|
||||
} catch (IOException e) {
|
||||
log.error("Error deleting temporary zip file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class BlankPageController {
|
||||
return whitePixelPercentage >= whitePercent;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/remove-blanks")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-blanks")
|
||||
@Operation(
|
||||
summary = "Remove blank pages from a PDF file",
|
||||
description =
|
||||
|
@ -32,7 +32,6 @@ import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -659,7 +658,7 @@ public class CompressController {
|
||||
};
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/compress-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/compress-pdf")
|
||||
@Operation(
|
||||
summary = "Optimize PDF file",
|
||||
description =
|
||||
|
@ -38,7 +38,7 @@ public class DecompressPdfController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/decompress-pdf", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/decompress-pdf", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Decompress PDF streams",
|
||||
description = "Fully decompresses all PDF streams including text content")
|
||||
|
@ -50,7 +50,7 @@ public class ExtractImageScansController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/extract-image-scans")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
|
||||
@Operation(
|
||||
summary = "Extract image scans from an input file",
|
||||
description =
|
||||
|
@ -54,7 +54,7 @@ public class ExtractImagesController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/extract-images")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/extract-images")
|
||||
@Operation(
|
||||
summary = "Extract images from a PDF file",
|
||||
description =
|
||||
|
@ -11,7 +11,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -39,7 +38,7 @@ public class FlattenController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/flatten")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
|
||||
@Operation(
|
||||
summary = "Flatten PDF form fields or full page",
|
||||
description =
|
||||
|
@ -10,7 +10,6 @@ import java.util.Map.Entry;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -52,7 +51,7 @@ public class MetadataController {
|
||||
binder.registerCustomEditor(Map.class, "allRequestParams", new StringToMapPropertyEditor());
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/update-metadata")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/update-metadata")
|
||||
@Operation(
|
||||
summary = "Update metadata of a PDF file",
|
||||
description =
|
||||
|
@ -76,7 +76,7 @@ public class OCRController {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/ocr-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
|
||||
@Operation(
|
||||
summary = "Process a PDF file with OCR",
|
||||
description =
|
||||
|
@ -3,7 +3,6 @@ package stirling.software.SPDF.controller.api.misc;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -32,7 +31,7 @@ public class OverlayImageController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/add-image")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-image")
|
||||
@Operation(
|
||||
summary = "Overlay image onto a PDF file",
|
||||
description =
|
||||
|
@ -39,7 +39,7 @@ public class PageNumbersController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(value = "/add-page-numbers", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Add page numbers to a PDF document",
|
||||
description =
|
||||
|
@ -18,7 +18,6 @@ import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.printing.PDFPageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -38,7 +37,7 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
||||
public class PrintFileController {
|
||||
|
||||
// TODO
|
||||
// @PostMapping(value = "/print-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
// @PostMapping(value = "/print-file", consumes = "multipart/form-data")
|
||||
// @Operation(
|
||||
// summary = "Prints PDF/Image file to a set printer",
|
||||
// description =
|
||||
@ -70,7 +69,7 @@ public class PrintFileController {
|
||||
|
||||
log.info("Selected Printer: " + selectedService.getName());
|
||||
|
||||
if (MediaType.APPLICATION_PDF_VALUE.equals(contentType)) {
|
||||
if ("application/pdf".equals(contentType)) {
|
||||
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
job.setPrintService(selectedService);
|
||||
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -47,7 +46,7 @@ public class RepairController {
|
||||
return endpointConfiguration.isGroupEnabled("qpdf");
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/repair")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/repair")
|
||||
@Operation(
|
||||
summary = "Repair a PDF file",
|
||||
description =
|
||||
|
@ -27,7 +27,7 @@ public class ReplaceAndInvertColorController {
|
||||
|
||||
private final ReplaceAndInvertColorService replaceAndInvertColorService;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/replace-invert-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/replace-invert-pdf")
|
||||
@Operation(
|
||||
summary = "Replace-Invert Color PDF",
|
||||
description =
|
||||
|
@ -52,7 +52,7 @@ public class ScannerEffectController {
|
||||
private static final int MAX_IMAGE_HEIGHT = 8192;
|
||||
private static final long MAX_IMAGE_PIXELS = 16_777_216; // 4096x4096
|
||||
|
||||
@PostMapping(value = "/scanner-effect", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/scanner-effect", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Apply scanner effect to PDF",
|
||||
description =
|
||||
|
@ -32,7 +32,7 @@ public class ShowJavascript {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/show-javascript")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/show-javascript")
|
||||
@Operation(
|
||||
summary = "Grabs all JS from a PDF and returns a single JS file with all code",
|
||||
description = "desc. Input:PDF Output:JS Type:SISO")
|
||||
|
@ -25,7 +25,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
@ -73,7 +72,7 @@ public class StampController {
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/add-stamp")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-stamp")
|
||||
@Operation(
|
||||
summary = "Add stamp to a PDF file",
|
||||
description =
|
||||
|
@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.common.PDStream;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -38,7 +37,7 @@ public class UnlockPDFFormsController {
|
||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/unlock-pdf-forms")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms")
|
||||
@Operation(
|
||||
summary = "Remove read-only property from form fields",
|
||||
description =
|
||||
|
@ -188,7 +188,7 @@ public class GetInfoOnPDF {
|
||||
return false;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/get-info-on-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
|
||||
@Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO")
|
||||
public ResponseEntity<byte[]> getPdfInfo(@ModelAttribute PDFFile request) throws IOException {
|
||||
MultipartFile inputFile = request.getFileInput();
|
||||
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
|
||||
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -33,7 +32,7 @@ public class PasswordController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/remove-password")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-password")
|
||||
@Operation(
|
||||
summary = "Remove password from a PDF file",
|
||||
description =
|
||||
@ -59,7 +58,7 @@ public class PasswordController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/add-password")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-password")
|
||||
@Operation(
|
||||
summary = "Add password to a PDF file",
|
||||
description =
|
||||
|
@ -34,7 +34,6 @@ import org.apache.pdfbox.pdmodel.common.PDStream;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
@ -98,7 +97,7 @@ public class RedactController {
|
||||
List.class, "redactions", new StringToArrayListPropertyEditor());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/redact", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/redact", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Redact PDF manually",
|
||||
description =
|
||||
@ -495,7 +494,7 @@ public class RedactController {
|
||||
return pageNumbers;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/auto-redact", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PostMapping(value = "/auto-redact", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
summary = "Redact PDF automatically",
|
||||
description =
|
||||
|
@ -7,7 +7,6 @@ import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -33,7 +32,7 @@ public class RemoveCertSignController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/remove-cert-sign")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign")
|
||||
@Operation(
|
||||
summary = "Remove digital signature from PDF",
|
||||
description =
|
||||
|
@ -21,7 +21,6 @@ import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -47,7 +46,7 @@ public class SanitizeController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/sanitize-pdf")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf")
|
||||
@Operation(
|
||||
summary = "Sanitize a PDF file",
|
||||
description =
|
||||
|
@ -24,7 +24,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
@ -65,7 +64,7 @@ public class WatermarkController {
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/add-watermark")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/add-watermark")
|
||||
@Operation(
|
||||
summary = "Add watermark to a PDF file",
|
||||
description =
|
||||
|
@ -1,6 +1,5 @@
|
||||
package stirling.software.SPDF.model.api.converters;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -19,7 +18,7 @@ import stirling.software.common.util.PDFToFile;
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertPDFToMarkdown {
|
||||
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/pdf/markdown")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/markdown")
|
||||
@Operation(
|
||||
summary = "Convert PDF to Markdown",
|
||||
description =
|
||||
|
@ -260,7 +260,7 @@ public class JobController {
|
||||
"fileName",
|
||||
"unknown",
|
||||
"contentType",
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE,
|
||||
"application/octet-stream",
|
||||
"fileSize",
|
||||
fileSize));
|
||||
}
|
||||
@ -295,9 +295,7 @@ public class JobController {
|
||||
|
||||
String fileName = resultFile != null ? resultFile.getFileName() : "download";
|
||||
String contentType =
|
||||
resultFile != null
|
||||
? resultFile.getContentType()
|
||||
: MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
resultFile != null ? resultFile.getContentType() : "application/octet-stream";
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Type", contentType)
|
||||
|
@ -24,7 +24,6 @@ import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
@ -57,10 +56,7 @@ class EditTableOfContentsControllerTest {
|
||||
void setUp() {
|
||||
mockFile =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content".getBytes());
|
||||
"file", "test.pdf", "application/pdf", "PDF content".getBytes());
|
||||
mockDocument = mock(PDDocument.class);
|
||||
mockCatalog = mock(PDDocumentCatalog.class);
|
||||
mockPages = mock(PDPageTree.class);
|
||||
|
@ -23,7 +23,6 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -50,22 +49,13 @@ class MergeControllerTest {
|
||||
void setUp() {
|
||||
mockFile1 =
|
||||
new MockMultipartFile(
|
||||
"file1",
|
||||
"document1.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content 1".getBytes());
|
||||
"file1", "document1.pdf", "application/pdf", "PDF content 1".getBytes());
|
||||
mockFile2 =
|
||||
new MockMultipartFile(
|
||||
"file2",
|
||||
"document2.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content 2".getBytes());
|
||||
"file2", "document2.pdf", "application/pdf", "PDF content 2".getBytes());
|
||||
mockFile3 =
|
||||
new MockMultipartFile(
|
||||
"file3",
|
||||
"chapter3.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content 3".getBytes());
|
||||
"file3", "chapter3.pdf", "application/pdf", "PDF content 3".getBytes());
|
||||
|
||||
mockDocument = mock(PDDocument.class);
|
||||
mockMergedDocument = mock(PDDocument.class);
|
||||
@ -212,10 +202,7 @@ class MergeControllerTest {
|
||||
// Given
|
||||
MockMultipartFile fileWithoutExtension =
|
||||
new MockMultipartFile(
|
||||
"file",
|
||||
"document_no_ext",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content".getBytes());
|
||||
"file", "document_no_ext", "application/pdf", "PDF content".getBytes());
|
||||
MultipartFile[] files = {fileWithoutExtension};
|
||||
|
||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
||||
|
@ -17,7 +17,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
@ -35,8 +34,7 @@ public class RotationControllerTest {
|
||||
public void testRotatePDF() throws IOException {
|
||||
// Create a mock file
|
||||
MockMultipartFile mockFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, new byte[] {1, 2, 3});
|
||||
new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
|
||||
RotatePDFRequest request = new RotatePDFRequest();
|
||||
request.setFileInput(mockFile);
|
||||
request.setAngle(90);
|
||||
@ -64,8 +62,7 @@ public class RotationControllerTest {
|
||||
public void testRotatePDFInvalidAngle() throws IOException {
|
||||
// Create a mock file
|
||||
MockMultipartFile mockFile =
|
||||
new MockMultipartFile(
|
||||
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, new byte[] {1, 2, 3});
|
||||
new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
|
||||
RotatePDFRequest request = new RotatePDFRequest();
|
||||
request.setFileInput(mockFile);
|
||||
request.setAngle(45); // Invalid angle
|
||||
|
@ -16,7 +16,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -46,22 +45,13 @@ class AttachmentControllerTest {
|
||||
void setUp() {
|
||||
pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"PDF content".getBytes());
|
||||
"fileInput", "test.pdf", "application/pdf", "PDF content".getBytes());
|
||||
attachment1 =
|
||||
new MockMultipartFile(
|
||||
"attachment1",
|
||||
"file1.txt",
|
||||
MediaType.TEXT_PLAIN_VALUE,
|
||||
"File 1 content".getBytes());
|
||||
"attachment1", "file1.txt", "text/plain", "File 1 content".getBytes());
|
||||
attachment2 =
|
||||
new MockMultipartFile(
|
||||
"attachment2",
|
||||
"file2.jpg",
|
||||
MediaType.IMAGE_JPEG_VALUE,
|
||||
"Image content".getBytes());
|
||||
"attachment2", "file2.jpg", "image/jpeg", "Image content".getBytes());
|
||||
request = new AddAttachmentRequest();
|
||||
mockDocument = mock(PDDocument.class);
|
||||
modifiedMockDocument = mock(PDDocument.class);
|
||||
|
@ -18,7 +18,6 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -118,8 +117,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithPfx() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile pfxFile =
|
||||
new MockMultipartFile("p12File", "test-cert.pfx", "application/x-pkcs12", pfxBytes);
|
||||
|
||||
@ -144,8 +142,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithPkcs12() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile p12File =
|
||||
new MockMultipartFile("p12File", "test-cert.p12", "application/x-pkcs12", p12Bytes);
|
||||
|
||||
@ -170,8 +167,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithJks() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile jksFile =
|
||||
new MockMultipartFile(
|
||||
"jksFile", "test-cert.jks", "application/octet-stream", jksBytes);
|
||||
@ -197,8 +193,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithPem() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile keyFile =
|
||||
new MockMultipartFile(
|
||||
"privateKeyFile", "test-key.pem", "application/x-pem-file", pemKeyBytes);
|
||||
@ -228,8 +223,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithCrt() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile keyFile =
|
||||
new MockMultipartFile(
|
||||
"privateKeyFile", "test-key.key", "application/x-pem-file", keyBytes);
|
||||
@ -259,8 +253,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithCer() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile keyFile =
|
||||
new MockMultipartFile(
|
||||
"privateKeyFile", "test-key.key", "application/x-pem-file", keyBytes);
|
||||
@ -290,8 +283,7 @@ class CertSignControllerTest {
|
||||
@Test
|
||||
void testSignPdfWithDer() throws Exception {
|
||||
MockMultipartFile pdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "test.pdf", MediaType.APPLICATION_PDF_VALUE, pdfBytes);
|
||||
new MockMultipartFile("fileInput", "test.pdf", "application/pdf", pdfBytes);
|
||||
MockMultipartFile keyFile =
|
||||
new MockMultipartFile(
|
||||
"privateKeyFile", "test-key.key", "application/x-pem-file", keyBytes);
|
||||
|
@ -42,7 +42,6 @@ import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
@ -131,10 +130,7 @@ class RedactControllerTest {
|
||||
void setUp() throws IOException {
|
||||
mockPdfFile =
|
||||
new MockMultipartFile(
|
||||
"fileInput",
|
||||
"test.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
createSimplePdfContent());
|
||||
"fileInput", "test.pdf", "application/pdf", createSimplePdfContent());
|
||||
|
||||
// Mock PDF document and related objects
|
||||
mockDocument = mock(PDDocument.class);
|
||||
@ -636,7 +632,7 @@ class RedactControllerTest {
|
||||
new MockMultipartFile(
|
||||
"fileInput",
|
||||
"malformed.pdf",
|
||||
MediaType.APPLICATION_PDF_VALUE,
|
||||
"application/pdf",
|
||||
"Not a real PDF content".getBytes());
|
||||
|
||||
RedactPdfRequest request = new RedactPdfRequest();
|
||||
|
@ -11,7 +11,6 @@ import java.util.List;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
class AttachmentServiceTest {
|
||||
@ -55,13 +54,13 @@ class AttachmentServiceTest {
|
||||
when(attachment1.getInputStream())
|
||||
.thenReturn(new ByteArrayInputStream("PDF content".getBytes()));
|
||||
when(attachment1.getSize()).thenReturn(15L);
|
||||
when(attachment1.getContentType()).thenReturn(MediaType.APPLICATION_PDF_VALUE);
|
||||
when(attachment1.getContentType()).thenReturn("application/pdf");
|
||||
|
||||
when(attachment2.getOriginalFilename()).thenReturn("image.jpg");
|
||||
when(attachment2.getInputStream())
|
||||
.thenReturn(new ByteArrayInputStream("Image content".getBytes()));
|
||||
when(attachment2.getSize()).thenReturn(20L);
|
||||
when(attachment2.getContentType()).thenReturn(MediaType.IMAGE_JPEG_VALUE);
|
||||
when(attachment2.getContentType()).thenReturn("image/jpeg");
|
||||
|
||||
PDDocument result = attachmentService.addAttachment(document, attachments);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package stirling.software.common.controller;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Map;
|
||||
@ -12,7 +11,6 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
@ -128,7 +126,7 @@ class JobControllerTest {
|
||||
String jobId = "test-job-id";
|
||||
String fileId = "file-id";
|
||||
String originalFileName = "test.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
byte[] fileContent = "Test file content".getBytes();
|
||||
|
||||
JobResult mockResult = new JobResult();
|
||||
@ -208,7 +206,7 @@ class JobControllerTest {
|
||||
String jobId = "test-job-id";
|
||||
String fileId = "file-id";
|
||||
String originalFileName = "test.pdf";
|
||||
String contentType = MediaType.APPLICATION_PDF_VALUE;
|
||||
String contentType = "application/pdf";
|
||||
|
||||
JobResult mockResult = new JobResult();
|
||||
mockResult.setJobId(jobId);
|
||||
|
@ -13,7 +13,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
@ -113,8 +112,8 @@ public class AuditUtils {
|
||||
&& req.getContentType() != null) {
|
||||
|
||||
String contentType = req.getContentType();
|
||||
if (contentType.contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
|| contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE)) {
|
||||
if (contentType.contains("application/x-www-form-urlencoded")
|
||||
|| contentType.contains("multipart/form-data")) {
|
||||
|
||||
Map<String, String[]> params = new HashMap<>(req.getParameterMap());
|
||||
// Remove CSRF token from logged parameters
|
||||
|
@ -71,12 +71,9 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
authentication.getClass().getSimpleName());
|
||||
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
|
||||
}
|
||||
} else if (jwtService != null) {
|
||||
String token = jwtService.extractToken(request);
|
||||
if (token != null && !token.isBlank()) {
|
||||
jwtService.clearToken(response);
|
||||
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
|
||||
}
|
||||
} else if (!jwtService.extractToken(request).isBlank()) {
|
||||
jwtService.clearToken(response);
|
||||
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
|
||||
} else {
|
||||
// Redirect to login page after logout
|
||||
String path = checkForErrors(request);
|
||||
@ -168,8 +165,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
log.info("Redirecting to Keycloak logout URL: {}", logoutUrl);
|
||||
} else {
|
||||
log.info(
|
||||
"No redirect URL for {} available. Redirecting to default logout URL:"
|
||||
+ " {}",
|
||||
"No redirect URL for {} available. Redirecting to default logout URL: {}",
|
||||
registrationId,
|
||||
logoutUrl);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public class DatabaseController {
|
||||
@Operation(
|
||||
summary = "Import a database backup file",
|
||||
description = "Uploads and imports a database backup SQL file.")
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "import-database")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "import-database")
|
||||
public String importDatabase(
|
||||
@Parameter(description = "SQL file to import", required = true)
|
||||
@RequestParam("fileInput")
|
||||
|
@ -2,7 +2,6 @@ package stirling.software.proprietary.security.controller.api;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.mail.MailSendException;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
@ -43,7 +42,7 @@ public class EmailController {
|
||||
* attachment.
|
||||
* @return ResponseEntity with success or error message.
|
||||
*/
|
||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/send-email")
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/send-email")
|
||||
@Operation(
|
||||
summary = "Send an email with an attachment",
|
||||
description =
|
||||
|
Loading…
x
Reference in New Issue
Block a user