API cleanups

This commit is contained in:
Anthony Stirling 2025-09-17 11:05:05 +01:00
parent 5e36291e28
commit 7c1ea71810
59 changed files with 970 additions and 70 deletions

View File

@ -72,5 +72,4 @@ public class OpenApiConfig {
.addSecurityItem(new SecurityRequirement().addList("apiKey")); .addSecurityItem(new SecurityRequirement().addList("apiKey"));
} }
} }
} }

View File

@ -10,14 +10,24 @@ public class SpringDocConfig {
@Bean @Bean
public GroupedOpenApi pdfProcessingApi() { public GroupedOpenApi pdfProcessingApi() {
return GroupedOpenApi.builder() return GroupedOpenApi.builder()
.group("pdf-processing") .group("file-processing")
.displayName("PDF Processing API") .displayName("File Processing")
.pathsToMatch("/api/v1/**") .pathsToMatch("/api/v1/**")
.pathsToExclude("/api/v1/admin/**", "/api/v1/user/**", "/api/v1/settings/**", "/api/v1/ui-data/**", "/api/v1/info/**", "/api/v1/general/job/**", "/api/v1/general/files/**") .pathsToExclude(
.addOpenApiCustomizer(openApi -> { "/api/v1/admin/**",
openApi.info(openApi.getInfo() "/api/v1/user/**",
"/api/v1/settings/**",
"/api/v1/ui-data/**",
"/api/v1/info/**",
"/api/v1/general/job/**",
"/api/v1/general/files/**")
.addOpenApiCustomizer(
openApi -> {
openApi.info(
openApi.getInfo()
.title("Stirling PDF - Processing API") .title("Stirling PDF - Processing API")
.description("API documentation for PDF processing operations including conversion, manipulation, security, and utility functions.")); .description(
"API documentation for PDF processing operations including conversion, manipulation, security, and utility functions."));
}) })
.build(); .build();
} }
@ -25,13 +35,16 @@ public class SpringDocConfig {
@Bean @Bean
public GroupedOpenApi adminApi() { public GroupedOpenApi adminApi() {
return GroupedOpenApi.builder() return GroupedOpenApi.builder()
.group("admin") .group("management")
.displayName("Admin & Management API") .displayName("Management")
.pathsToMatch("/api/v1/admin/**", "/api/v1/user/**", "/api/v1/settings/**") .pathsToMatch("/api/v1/admin/**", "/api/v1/user/**", "/api/v1/settings/**")
.addOpenApiCustomizer(openApi -> { .addOpenApiCustomizer(
openApi.info(openApi.getInfo() openApi -> {
openApi.info(
openApi.getInfo()
.title("Stirling PDF - Admin API") .title("Stirling PDF - Admin API")
.description("API documentation for administrative functions, user management, settings, and system configuration.")); .description(
"API documentation for administrative functions, user management, settings, and system configuration."));
}) })
.build(); .build();
} }
@ -41,11 +54,18 @@ public class SpringDocConfig {
return GroupedOpenApi.builder() return GroupedOpenApi.builder()
.group("system") .group("system")
.displayName("System & UI API") .displayName("System & UI API")
.pathsToMatch("/api/v1/ui-data/**", "/api/v1/info/**", "/api/v1/general/job/**", "/api/v1/general/files/**") .pathsToMatch(
.addOpenApiCustomizer(openApi -> { "/api/v1/ui-data/**",
openApi.info(openApi.getInfo() "/api/v1/info/**",
"/api/v1/general/job/**",
"/api/v1/general/files/**")
.addOpenApiCustomizer(
openApi -> {
openApi.info(
openApi.getInfo()
.title("Stirling PDF - System API") .title("Stirling PDF - System API")
.description("API documentation for system information, UI data, and general utility endpoints.")); .description(
"API documentation for system information, UI data, and general utility endpoints."));
}) })
.build(); .build();
} }

View File

@ -0,0 +1,69 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* API response annotation for conversion operations that output non-PDF formats. Use for PDF to
* Word, Excel, PowerPoint, text, HTML, CSV, etc.
*
* <p>Specify the output formats this endpoint supports.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ConversionResponse {
/**
* The output formats this conversion endpoint supports. Use OutputFormat enum values to specify
* supported formats.
*/
OutputFormat[] value() default {OutputFormat.DOCX, OutputFormat.TXT, OutputFormat.RTF};
/** Supported output formats for conversion operations */
enum OutputFormat {
DOCX(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Microsoft Word document (DOCX)",
"binary"),
DOC("application/msword", "Microsoft Word document (DOC)", "binary"),
XLSX(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Microsoft Excel document (XLSX)",
"binary"),
PPTX(
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"Microsoft PowerPoint document (PPTX)",
"binary"),
RTF("application/rtf", "Rich Text Format document", "binary"),
TXT("text/plain", "Plain text content", "string"),
HTML("text/html", "HTML content", "string"),
CSV("text/csv", "CSV data", "string"),
XML("application/xml", "XML document", "string"),
JSON("application/json", "JSON data", "string"),
BINARY("application/octet-stream", "Binary file output", "binary");
private final String mediaType;
private final String description;
private final String schemaFormat;
OutputFormat(String mediaType, String description, String schemaFormat) {
this.mediaType = mediaType;
this.description = description;
this.schemaFormat = schemaFormat;
}
public String getMediaType() {
return mediaType;
}
public String getDescription() {
return description;
}
public String getSchemaFormat() {
return schemaFormat;
}
}
}

View File

@ -0,0 +1,30 @@
package stirling.software.SPDF.config.swagger;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Standard error response")
public class ErrorResponse {
@Schema(description = "HTTP status code", example = "400")
private int status;
@Schema(
description = "Error message describing what went wrong",
example = "Invalid PDF file or corrupted data")
private String message;
@Schema(description = "Timestamp when the error occurred", example = "2024-01-15T10:30:00Z")
private String timestamp;
@Schema(
description = "Request path where the error occurred",
example = "/api/v1/general/rotate-pdf")
private String path;
}

View File

@ -0,0 +1,67 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for filter operations that conditionally return the original file. Use
* for operations like text filters, page count filters, size filters, etc. Returns the original PDF
* if condition is met, otherwise returns no content (204).
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "Filter condition met - returns the original PDF file",
content =
@Content(
mediaType = "application/pdf",
schema =
@Schema(
type = "string",
format = "binary",
description = "The original PDF file"))),
@ApiResponse(
responseCode = "204",
description = "Filter condition not met - no content returned",
content = @Content()),
@ApiResponse(
responseCode = "400",
description = "Bad request - Invalid filter parameters or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description =
"Unprocessable entity - PDF is valid but cannot be analyzed for filtering",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description = "Internal server error - Unexpected error during PDF analysis",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface FilterResponse {}

View File

@ -0,0 +1,63 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for operations that return JSON data or analysis results. Use for
* analysis operations, metadata extraction, info operations, etc.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "Analysis or data extraction completed successfully",
content =
@Content(
mediaType = "application/json",
schema =
@Schema(
type = "object",
description =
"JSON object containing the requested data or analysis results"))),
@ApiResponse(
responseCode = "400",
description = "Bad request - Invalid input parameters or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description =
"Unprocessable entity - PDF is valid but cannot be analyzed or processed",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description =
"Internal server error - Unexpected error during analysis or processing",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface JsonDataResponse {}

View File

@ -0,0 +1,86 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for operations that may return multiple files or a ZIP archive. Use for
* operations like PDF to images, split PDF, or multiple file conversions.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description =
"Files processed successfully. Returns single file or ZIP archive containing multiple files.",
content = {
@Content(
mediaType = "application/pdf",
schema =
@Schema(
type = "string",
format = "binary",
description = "Single PDF file result")),
@Content(
mediaType = "application/zip",
schema =
@Schema(
type = "string",
format = "binary",
description =
"ZIP archive containing multiple output files")),
@Content(
mediaType = "image/png",
schema =
@Schema(
type = "string",
format = "binary",
description = "Single image file (PNG)")),
@Content(
mediaType = "image/jpeg",
schema =
@Schema(
type = "string",
format = "binary",
description = "Single image file (JPEG)"))
}),
@ApiResponse(
responseCode = "400",
description =
"Bad request - Invalid input parameters, unsupported file format, or corrupted files",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - Files exceed maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description = "Unprocessable entity - Files are valid but cannot be processed",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description = "Internal server error - Unexpected error during file processing",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface MultiFileResponse {}

View File

@ -0,0 +1,72 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* API response annotation for PDF to Microsoft Office format conversions. Specify the exact output
* format(s) this endpoint supports.
*
* <p>Usage: @OfficeConversionResponse(OfficeFormat.DOCX) @OfficeConversionResponse({OfficeFormat.DOCX,
* OfficeFormat.DOC})
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OfficeConversionResponse {
/** The Office formats this endpoint supports. */
OfficeFormat[] value();
/** Supported Microsoft Office output formats */
enum OfficeFormat {
DOCX(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Microsoft Word document (DOCX)",
"Word document"),
DOC("application/msword", "Microsoft Word document (DOC)", "Word document (legacy)"),
XLSX(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Microsoft Excel document (XLSX)",
"Excel spreadsheet"),
PPTX(
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"Microsoft PowerPoint document (PPTX)",
"PowerPoint presentation"),
ODT(
"application/vnd.oasis.opendocument.text",
"OpenDocument Text document (ODT)",
"OpenDocument text"),
ODS(
"application/vnd.oasis.opendocument.spreadsheet",
"OpenDocument Spreadsheet (ODS)",
"OpenDocument spreadsheet"),
ODP(
"application/vnd.oasis.opendocument.presentation",
"OpenDocument Presentation (ODP)",
"OpenDocument presentation");
private final String mediaType;
private final String description;
private final String shortDescription;
OfficeFormat(String mediaType, String description, String shortDescription) {
this.mediaType = mediaType;
this.description = description;
this.shortDescription = shortDescription;
}
public String getMediaType() {
return mediaType;
}
public String getDescription() {
return description;
}
public String getShortDescription() {
return shortDescription;
}
}
}

View File

@ -0,0 +1,66 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for PDF to PowerPoint presentation conversions. Use for endpoints that
* convert PDF to PPTX format.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "PDF converted successfully to PowerPoint presentation",
content =
@Content(
mediaType =
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
schema =
@Schema(
type = "string",
format = "binary",
description =
"Microsoft PowerPoint presentation (PPTX)"))),
@ApiResponse(
responseCode = "400",
description =
"Bad request - Invalid input parameters, unsupported format, or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description =
"Unprocessable entity - PDF is valid but cannot be converted to PowerPoint format",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description =
"Internal server error - Unexpected error during PowerPoint conversion",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface PowerPointConversionResponse {}

View File

@ -0,0 +1,63 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* Standard API response annotation for PDF operations that take PDF input and return PDF output.
* Use for single PDF input single PDF output (SISO) operations like rotate, compress, etc.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "PDF processed successfully",
content =
@Content(
mediaType = "application/pdf",
schema =
@Schema(
type = "string",
format = "binary",
description = "The processed PDF file"))),
@ApiResponse(
responseCode = "400",
description =
"Bad request - Invalid input parameters, unsupported file format, or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description =
"Unprocessable entity - PDF is valid but cannot be processed (e.g., encrypted, corrupted)",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description = "Internal server error - Unexpected error during PDF processing",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface StandardPdfResponse {}

View File

@ -0,0 +1,54 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* API response annotation for PDF to text/document format conversions. Specify the exact output
* format(s) this endpoint supports.
*
* <p>Usage: @TextConversionResponse(TextFormat.TXT) @TextConversionResponse({TextFormat.TXT,
* TextFormat.RTF})
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TextConversionResponse {
/** The text/document formats this endpoint supports. */
TextFormat[] value();
/** Supported text and document output formats */
enum TextFormat {
TXT("text/plain", "Plain text file", "Plain text"),
RTF("application/rtf", "Rich Text Format document", "RTF document"),
HTML("text/html", "HTML document", "HTML file"),
XML("application/xml", "XML document", "XML file"),
CSV("text/csv", "Comma-separated values file", "CSV data"),
JSON("application/json", "JSON document", "JSON data"),
MARKDOWN("text/markdown", "Markdown document", "Markdown file");
private final String mediaType;
private final String description;
private final String shortDescription;
TextFormat(String mediaType, String description, String shortDescription) {
this.mediaType = mediaType;
this.description = description;
this.shortDescription = shortDescription;
}
public String getMediaType() {
return mediaType;
}
public String getDescription() {
return description;
}
public String getShortDescription() {
return shortDescription;
}
}
}

View File

@ -0,0 +1,69 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for PDF to plain text conversions. Use for endpoints that extract text
* content from PDF.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "PDF text extracted successfully",
content = {
@Content(
mediaType = "text/plain",
schema =
@Schema(
type = "string",
description =
"Plain text content extracted from PDF")),
@Content(
mediaType = "application/rtf",
schema =
@Schema(
type = "string",
format = "binary",
description = "Rich Text Format document"))
}),
@ApiResponse(
responseCode = "400",
description = "Bad request - Invalid input parameters or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description = "Unprocessable entity - PDF is valid but text extraction failed",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description = "Internal server error - Unexpected error during text extraction",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface TextPlainConversionResponse {}

View File

@ -0,0 +1,72 @@
package stirling.software.SPDF.config.swagger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
/**
* API response annotation for PDF to Word document conversions. Use for endpoints that convert PDF
* to DOCX/DOC formats.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "PDF converted successfully to Word document",
content = {
@Content(
mediaType =
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
schema =
@Schema(
type = "string",
format = "binary",
description = "Microsoft Word document (DOCX)")),
@Content(
mediaType = "application/msword",
schema =
@Schema(
type = "string",
format = "binary",
description = "Microsoft Word document (DOC)"))
}),
@ApiResponse(
responseCode = "400",
description =
"Bad request - Invalid input parameters, unsupported format, or corrupted PDF",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "413",
description = "Payload too large - File exceeds maximum allowed size",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "422",
description =
"Unprocessable entity - PDF is valid but cannot be converted to Word format",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(
responseCode = "500",
description = "Internal server error - Unexpected error during Word conversion",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))
})
public @interface WordConversionResponse {}

View File

@ -18,6 +18,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.JsonDataResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -31,6 +32,7 @@ public class AnalysisController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/page-count", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/page-count", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get PDF page count", summary = "Get PDF page count",
description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO")
@ -41,6 +43,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/basic-info", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/basic-info", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get basic PDF information", summary = "Get basic PDF information",
description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO")
@ -55,6 +58,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/document-properties", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/document-properties", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get PDF document properties", summary = "Get PDF document properties",
description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO")
@ -78,6 +82,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/page-dimensions", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/page-dimensions", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get page dimensions for all pages", summary = "Get page dimensions for all pages",
description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO")
@ -98,6 +103,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/form-fields", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/form-fields", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get form field information", summary = "Get form field information",
description = description =
@ -121,6 +127,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/annotation-info", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/annotation-info", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get annotation information", summary = "Get annotation information",
description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO")
@ -145,6 +152,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/font-info", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/font-info", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get font information", summary = "Get font information",
description = description =
@ -167,6 +175,7 @@ public class AnalysisController {
} }
@AutoJobPostMapping(value = "/security-info", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/security-info", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Get security information", summary = "Get security information",
description = description =

View File

@ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.BookletImpositionRequest; import stirling.software.SPDF.model.api.general.BookletImpositionRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -39,6 +40,7 @@ public class BookletImpositionController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/booklet-imposition", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/booklet-imposition", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Create a booklet with proper page imposition", summary = "Create a booklet with proper page imposition",
description = description =
@ -56,7 +58,8 @@ public class BookletImpositionController {
// Validate pages per sheet for booklet // Validate pages per sheet for booklet
if (pagesPerSheet != 2 && pagesPerSheet != 4) { if (pagesPerSheet != 2 && pagesPerSheet != 4) {
throw new IllegalArgumentException("pagesPerSheet must be 2 or 4 for booklet imposition"); throw new IllegalArgumentException(
"pagesPerSheet must be 2 or 4 for booklet imposition");
} }
PDDocument sourceDocument = pdfDocumentFactory.load(file); PDDocument sourceDocument = pdfDocumentFactory.load(file);
@ -65,8 +68,11 @@ public class BookletImpositionController {
// Step 1: Reorder pages for booklet (reusing logic from RearrangePagesPDFController) // Step 1: Reorder pages for booklet (reusing logic from RearrangePagesPDFController)
List<Integer> bookletOrder = getBookletPageOrder(bookletType, totalPages); List<Integer> bookletOrder = getBookletPageOrder(bookletType, totalPages);
// Step 2: Create new document with multi-page layout (reusing logic from MultiPageLayoutController) // Step 2: Create new document with multi-page layout (reusing logic from
PDDocument newDocument = createBookletWithLayout(sourceDocument, bookletOrder, pagesPerSheet, addBorder, pageOrientation); // MultiPageLayoutController)
PDDocument newDocument =
createBookletWithLayout(
sourceDocument, bookletOrder, pagesPerSheet, addBorder, pageOrientation);
sourceDocument.close(); sourceDocument.close();
@ -112,10 +118,16 @@ public class BookletImpositionController {
} }
// Reused and adapted logic from MultiPageLayoutController // Reused and adapted logic from MultiPageLayoutController
private PDDocument createBookletWithLayout(PDDocument sourceDocument, List<Integer> pageOrder, private PDDocument createBookletWithLayout(
int pagesPerSheet, boolean addBorder, String pageOrientation) throws IOException { PDDocument sourceDocument,
List<Integer> pageOrder,
int pagesPerSheet,
boolean addBorder,
String pageOrientation)
throws IOException {
PDDocument newDocument = pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDocument); PDDocument newDocument =
pdfDocumentFactory.createNewDocumentBasedOnOldDocument(sourceDocument);
int cols = pagesPerSheet == 2 ? 2 : 2; // 2x1 for 2 pages, 2x2 for 4 pages int cols = pagesPerSheet == 2 ? 2 : 2; // 2x1 for 2 pages, 2x2 for 4 pages
int rows = pagesPerSheet == 2 ? 1 : 2; int rows = pagesPerSheet == 2 ? 1 : 2;
@ -125,16 +137,23 @@ public class BookletImpositionController {
while (currentPageIndex < totalOrderedPages) { while (currentPageIndex < totalOrderedPages) {
// Use landscape orientation for booklets (A4 landscape -> A5 portrait when folded) // Use landscape orientation for booklets (A4 landscape -> A5 portrait when folded)
PDRectangle pageSize = "LANDSCAPE".equals(pageOrientation) ? PDRectangle pageSize =
new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth()) : PDRectangle.A4; "LANDSCAPE".equals(pageOrientation)
? new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())
: PDRectangle.A4;
PDPage newPage = new PDPage(pageSize); PDPage newPage = new PDPage(pageSize);
newDocument.addPage(newPage); newDocument.addPage(newPage);
float cellWidth = newPage.getMediaBox().getWidth() / cols; float cellWidth = newPage.getMediaBox().getWidth() / cols;
float cellHeight = newPage.getMediaBox().getHeight() / rows; float cellHeight = newPage.getMediaBox().getHeight() / rows;
PDPageContentStream contentStream = new PDPageContentStream( PDPageContentStream contentStream =
newDocument, newPage, PDPageContentStream.AppendMode.APPEND, true, true); new PDPageContentStream(
newDocument,
newPage,
PDPageContentStream.AppendMode.APPEND,
true,
true);
LayerUtility layerUtility = new LayerUtility(newDocument); LayerUtility layerUtility = new LayerUtility(newDocument);
if (addBorder) { if (addBorder) {
@ -143,7 +162,9 @@ public class BookletImpositionController {
} }
// Place pages on the current sheet // Place pages on the current sheet
for (int sheetPosition = 0; sheetPosition < pagesPerSheet && currentPageIndex < totalOrderedPages; sheetPosition++) { for (int sheetPosition = 0;
sheetPosition < pagesPerSheet && currentPageIndex < totalOrderedPages;
sheetPosition++) {
int sourcePageIndex = pageOrder.get(currentPageIndex); int sourcePageIndex = pageOrder.get(currentPageIndex);
PDPage sourcePage = sourceDocument.getPage(sourcePageIndex); PDPage sourcePage = sourceDocument.getPage(sourcePageIndex);
PDRectangle rect = sourcePage.getMediaBox(); PDRectangle rect = sourcePage.getMediaBox();
@ -156,14 +177,17 @@ public class BookletImpositionController {
int colIndex = sheetPosition % cols; int colIndex = sheetPosition % cols;
float x = colIndex * cellWidth + (cellWidth - rect.getWidth() * scale) / 2; float x = colIndex * cellWidth + (cellWidth - rect.getWidth() * scale) / 2;
float y = newPage.getMediaBox().getHeight() float y =
- ((rowIndex + 1) * cellHeight - (cellHeight - rect.getHeight() * scale) / 2); newPage.getMediaBox().getHeight()
- ((rowIndex + 1) * cellHeight
- (cellHeight - rect.getHeight() * scale) / 2);
contentStream.saveGraphicsState(); contentStream.saveGraphicsState();
contentStream.transform(Matrix.getTranslateInstance(x, y)); contentStream.transform(Matrix.getTranslateInstance(x, y));
contentStream.transform(Matrix.getScaleInstance(scale, scale)); contentStream.transform(Matrix.getScaleInstance(scale, scale));
PDFormXObject formXObject = layerUtility.importPageAsForm(sourceDocument, sourcePageIndex); PDFormXObject formXObject =
layerUtility.importPageAsForm(sourceDocument, sourcePageIndex);
contentStream.drawForm(formXObject); contentStream.drawForm(formXObject);
contentStream.restoreGraphicsState(); contentStream.restoreGraphicsState();

View File

@ -20,6 +20,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.CropPdfForm; import stirling.software.SPDF.model.api.general.CropPdfForm;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -34,6 +35,7 @@ public class CropController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/crop", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/crop", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Crops a PDF document", summary = "Crops a PDF document",
description = description =

View File

@ -29,6 +29,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.JsonDataResponse;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.EditTableOfContentsRequest; import stirling.software.SPDF.model.api.EditTableOfContentsRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -45,6 +47,7 @@ public class EditTableOfContentsController {
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@AutoJobPostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/extract-bookmarks", consumes = "multipart/form-data")
@JsonDataResponse
@Operation( @Operation(
summary = "Extract PDF Bookmarks", summary = "Extract PDF Bookmarks",
description = "Extracts bookmarks/table of contents from a PDF document as JSON.") description = "Extracts bookmarks/table of contents from a PDF document as JSON.")
@ -153,6 +156,7 @@ public class EditTableOfContentsController {
} }
@AutoJobPostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/edit-table-of-contents", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Edit Table of Contents", summary = "Edit Table of Contents",
description = "Add or edit bookmarks/table of contents in a PDF document.") description = "Add or edit bookmarks/table of contents in a PDF document.")

View File

@ -32,6 +32,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.MergePdfsRequest; import stirling.software.SPDF.model.api.general.MergePdfsRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -155,6 +156,7 @@ public class MergeController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/merge-pdfs") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
@StandardPdfResponse
@Operation( @Operation(
summary = "Merge multiple PDF files into one", summary = "Merge multiple PDF files into one",
description = description =

View File

@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest; import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -37,6 +38,7 @@ public class MultiPageLayoutController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/multi-page-layout", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/multi-page-layout", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Merge multiple pages of a PDF document into a single page", summary = "Merge multiple pages of a PDF document into a single page",
description = description =

View File

@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.service.PdfImageRemovalService; import stirling.software.SPDF.service.PdfImageRemovalService;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
@ -47,11 +48,12 @@ public class PdfImageRemovalController {
* @throws IOException If an error occurs while processing the PDF file. * @throws IOException If an error occurs while processing the PDF file.
*/ */
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-image-pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Remove images from file to reduce the file size.", summary = "Remove images from file to reduce the file size.",
description = description =
"This endpoint remove images from file to reduce the file size.Input:PDF" "This endpoint remove images from file to reduce the file size.Input:PDF"
+ " Output:PDF Type:MISO") + " Output:PDF Type:SISO")
public ResponseEntity<byte[]> removeImages(@ModelAttribute PDFFile file) throws IOException { public ResponseEntity<byte[]> removeImages(@ModelAttribute PDFFile file) throws IOException {
// Load the PDF document // Load the PDF document
PDDocument document = pdfDocumentFactory.load(file); PDDocument document = pdfDocumentFactory.load(file);

View File

@ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.OverlayPdfsRequest; import stirling.software.SPDF.model.api.general.OverlayPdfsRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -40,6 +41,7 @@ public class PdfOverlayController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Overlay PDF files in various modes", summary = "Overlay PDF files in various modes",
description = description =

View File

@ -20,6 +20,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.SortTypes; import stirling.software.SPDF.model.SortTypes;
import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.SPDF.model.api.general.RearrangePagesRequest; import stirling.software.SPDF.model.api.general.RearrangePagesRequest;
@ -39,6 +40,7 @@ public class RearrangePagesPDFController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-pages") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-pages")
@StandardPdfResponse
@Operation( @Operation(
summary = "Remove pages from a PDF file", summary = "Remove pages from a PDF file",
description = description =
@ -238,6 +240,7 @@ public class RearrangePagesPDFController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/rearrange-pages") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rearrange-pages")
@StandardPdfResponse
@Operation( @Operation(
summary = "Rearrange pages in a PDF file", summary = "Rearrange pages in a PDF file",
description = description =

View File

@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.RotatePDFRequest; import stirling.software.SPDF.model.api.general.RotatePDFRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -32,6 +33,7 @@ public class RotationController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/rotate-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/rotate-pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Rotate a PDF file", summary = "Rotate a PDF file",
description = description =

View File

@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.general.ScalePagesRequest; import stirling.software.SPDF.model.api.general.ScalePagesRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -39,6 +40,7 @@ public class ScalePagesController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/scale-pages", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/scale-pages", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
summary = "Change the size of a PDF page/document", summary = "Change the size of a PDF page/document",
description = description =

View File

@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -42,6 +43,7 @@ public class SplitPDFController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/split-pages") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/split-pages")
@MultiFileResponse
@Operation( @Operation(
summary = "Split a PDF file into separate documents", summary = "Split a PDF file into separate documents",
description = description =

View File

@ -30,6 +30,7 @@ import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest; import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.PdfMetadata; import stirling.software.common.model.PdfMetadata;
@ -118,6 +119,7 @@ public class SplitPdfByChaptersController {
} }
@AutoJobPostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/split-pdf-by-chapters", consumes = "multipart/form-data")
@MultiFileResponse
@Operation( @Operation(
summary = "Split PDFs by Chapters", summary = "Split PDFs by Chapters",
description = "Splits a PDF into chapters and returns a ZIP file.") description = "Splits a PDF into chapters and returns a ZIP file.")

View File

@ -30,6 +30,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest; import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -44,6 +45,7 @@ public class SplitPdfBySectionsController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data")
@MultiFileResponse
@Operation( @Operation(
summary = "Split PDF pages into smaller sections", summary = "Split PDF pages into smaller sections",
description = description =

View File

@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest; import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -40,6 +41,7 @@ public class SplitPdfBySizeController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
@MultiFileResponse
@Operation( @Operation(
summary = "Auto split PDF pages into separate documents based on size or count", summary = "Auto split PDF pages into separate documents based on size or count",
description = description =

View File

@ -19,6 +19,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.converters.EmlToPdfRequest; import stirling.software.common.model.api.converters.EmlToPdfRequest;
@ -41,6 +42,7 @@ public class ConvertEmlToPDF {
private final CustomHtmlSanitizer customHtmlSanitizer; private final CustomHtmlSanitizer customHtmlSanitizer;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/eml/pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert EML to PDF", summary = "Convert EML to PDF",
description = description =

View File

@ -12,6 +12,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.converters.HTMLToPdfRequest; import stirling.software.common.model.api.converters.HTMLToPdfRequest;
@ -37,6 +38,7 @@ public class ConvertHtmlToPDF {
private final CustomHtmlSanitizer customHtmlSanitizer; private final CustomHtmlSanitizer customHtmlSanitizer;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/html/pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/html/pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF", summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
description = description =

View File

@ -30,6 +30,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest; import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest; import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
@ -52,6 +54,7 @@ public class ConvertImgPDFController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/img") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/img")
@MultiFileResponse
@Operation( @Operation(
summary = "Convert PDF to image(s)", summary = "Convert PDF to image(s)",
description = description =
@ -212,6 +215,7 @@ public class ConvertImgPDFController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/img/pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/img/pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert images to a PDF file", summary = "Convert images to a PDF file",
description = description =

View File

@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.GeneralFile; import stirling.software.common.model.api.GeneralFile;
@ -46,6 +47,7 @@ public class ConvertMarkdownToPdf {
private final CustomHtmlSanitizer customHtmlSanitizer; private final CustomHtmlSanitizer customHtmlSanitizer;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/markdown/pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert a Markdown file to PDF", summary = "Convert a Markdown file to PDF",
description = description =

View File

@ -9,6 +9,7 @@ import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.config.swagger.HtmlConversionResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.util.PDFToFile; import stirling.software.common.util.PDFToFile;
@ -23,6 +24,7 @@ public class ConvertPDFToHtml {
summary = "Convert PDF to HTML", summary = "Convert PDF to HTML",
description = description =
"This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO") "This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO")
@HtmlConversionResponse
public ResponseEntity<byte[]> processPdfToHTML(@ModelAttribute PDFFile file) throws Exception { public ResponseEntity<byte[]> processPdfToHTML(@ModelAttribute PDFFile file) throws Exception {
MultipartFile inputFile = file.getFileInput(); MultipartFile inputFile = file.getFileInput();
PDFToFile pdfToFile = new PDFToFile(); PDFToFile pdfToFile = new PDFToFile();

View File

@ -17,6 +17,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.PowerPointConversionResponse;
import stirling.software.SPDF.config.swagger.TextPlainConversionResponse;
import stirling.software.SPDF.config.swagger.WordConversionResponse;
import stirling.software.SPDF.config.swagger.XmlConversionResponse;
import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest; import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest;
import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest; import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest;
import stirling.software.SPDF.model.api.converters.PdfToWordRequest; import stirling.software.SPDF.model.api.converters.PdfToWordRequest;
@ -35,6 +39,7 @@ public class ConvertPDFToOffice {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/presentation") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/presentation")
@PowerPointConversionResponse
@Operation( @Operation(
summary = "Convert PDF to Presentation format", summary = "Convert PDF to Presentation format",
description = description =
@ -50,6 +55,7 @@ public class ConvertPDFToOffice {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/text") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/text")
@TextPlainConversionResponse
@Operation( @Operation(
summary = "Convert PDF to Text or RTF format", summary = "Convert PDF to Text or RTF format",
description = description =
@ -78,6 +84,7 @@ public class ConvertPDFToOffice {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/word") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/word")
@WordConversionResponse
@Operation( @Operation(
summary = "Convert PDF to Word document", summary = "Convert PDF to Word document",
description = description =
@ -92,6 +99,7 @@ public class ConvertPDFToOffice {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/xml") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/xml")
@XmlConversionResponse
@Operation( @Operation(
summary = "Convert PDF to XML", summary = "Convert PDF to XML",
description = description =

View File

@ -65,6 +65,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.converters.PdfToPdfARequest; import stirling.software.SPDF.model.api.converters.PdfToPdfARequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ExceptionUtils;
@ -79,6 +80,7 @@ import stirling.software.common.util.WebResponseUtils;
public class ConvertPDFToPDFA { public class ConvertPDFToPDFA {
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert a PDF to a PDF/A", summary = "Convert a PDF to a PDF/A",
description = description =

View File

@ -18,6 +18,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest; import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
@ -41,6 +42,7 @@ public class ConvertWebsiteToPDF {
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/url/pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/url/pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Convert a URL to a PDF", summary = "Convert a URL to a PDF",
description = description =

View File

@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.FilterResponse;
import stirling.software.SPDF.model.api.PDFComparisonAndCount; import stirling.software.SPDF.model.api.PDFComparisonAndCount;
import stirling.software.SPDF.model.api.PDFWithPageNums; import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.SPDF.model.api.filter.ContainsTextRequest; import stirling.software.SPDF.model.api.filter.ContainsTextRequest;
@ -38,6 +39,7 @@ public class FilterController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-text") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-text")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF contains set text, returns true if does", summary = "Checks if a PDF contains set text, returns true if does",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")
@ -56,6 +58,7 @@ public class FilterController {
// TODO // TODO
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-image") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-contains-image")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF contains an image", summary = "Checks if a PDF contains an image",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")
@ -72,6 +75,7 @@ public class FilterController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-count") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-count")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF is greater, less or equal to a setPageCount", summary = "Checks if a PDF is greater, less or equal to a setPageCount",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")
@ -105,6 +109,7 @@ public class FilterController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-size") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-size")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF is of a certain size", summary = "Checks if a PDF is of a certain size",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")
@ -148,6 +153,7 @@ public class FilterController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-file-size") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-file-size")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF is a set file size", summary = "Checks if a PDF is a set file size",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")
@ -181,6 +187,7 @@ public class FilterController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/filter-page-rotation")
@FilterResponse
@Operation( @Operation(
summary = "Checks if a PDF is of a certain rotation", summary = "Checks if a PDF is of a certain rotation",
description = "Input:PDF Output:Boolean Type:SISO") description = "Input:PDF Output:Boolean Type:SISO")

View File

@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.misc.AddAttachmentRequest; import stirling.software.SPDF.model.api.misc.AddAttachmentRequest;
import stirling.software.SPDF.service.AttachmentServiceInterface; import stirling.software.SPDF.service.AttachmentServiceInterface;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
@ -35,6 +36,7 @@ public class AttachmentController {
private final AttachmentServiceInterface pdfAttachmentService; private final AttachmentServiceInterface pdfAttachmentService;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-attachments") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-attachments")
@StandardPdfResponse
@Operation( @Operation(
summary = "Add attachments to PDF", summary = "Add attachments to PDF",
description = description =

View File

@ -33,6 +33,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest; import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -103,6 +104,7 @@ public class AutoSplitPdfController {
} }
@AutoJobPostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data")
@MultiFileResponse
@Operation( @Operation(
summary = "Auto split PDF pages into separate documents", summary = "Auto split PDF pages into separate documents",
description = description =

View File

@ -50,6 +50,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest; import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -659,6 +660,7 @@ public class CompressController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/compress-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/compress-pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Optimize PDF file", summary = "Optimize PDF file",
description = description =

View File

@ -38,6 +38,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.api.PDFExtractImagesRequest; import stirling.software.SPDF.model.api.PDFExtractImagesRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -55,6 +56,7 @@ public class ExtractImagesController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-images") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/extract-images")
@MultiFileResponse
@Operation( @Operation(
summary = "Extract images from a PDF file", summary = "Extract images from a PDF file",
description = description =

View File

@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.misc.FlattenRequest; import stirling.software.SPDF.model.api.misc.FlattenRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -39,6 +40,7 @@ public class FlattenController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/flatten") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/flatten")
@StandardPdfResponse
@Operation( @Operation(
summary = "Flatten PDF form fields or full page", summary = "Flatten PDF form fields or full page",
description = description =

View File

@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.misc.MetadataRequest; import stirling.software.SPDF.model.api.misc.MetadataRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -53,6 +54,7 @@ public class MetadataController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/update-metadata") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/update-metadata")
@StandardPdfResponse
@Operation( @Operation(
summary = "Update metadata of a PDF file", summary = "Update metadata of a PDF file",
description = description =

View File

@ -30,6 +30,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest; import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
@ -77,6 +78,7 @@ public class OCRController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Process a PDF file with OCR", summary = "Process a PDF file with OCR",
description = description =

View File

@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.config.EndpointConfiguration;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -47,6 +48,7 @@ public class RepairController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/repair") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/repair")
@StandardPdfResponse
@Operation( @Operation(
summary = "Repair a PDF file", summary = "Repair a PDF file",
description = description =

View File

@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -38,6 +39,7 @@ public class UnlockPDFFormsController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/unlock-pdf-forms")
@StandardPdfResponse
@Operation( @Operation(
summary = "Remove read-only property from form fields", summary = "Remove read-only property from form fields",
description = description =

View File

@ -20,11 +20,16 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.MultiFileResponse;
import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineOperation; import stirling.software.SPDF.model.PipelineOperation;
import stirling.software.SPDF.model.PipelineResult; import stirling.software.SPDF.model.PipelineResult;
@ -47,6 +52,45 @@ public class PipelineController {
private final PostHogService postHogService; private final PostHogService postHogService;
@AutoJobPostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @AutoJobPostMapping(value = "/handleData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@MultiFileResponse
@Operation(
summary = "Execute automated PDF processing pipeline",
description =
"This endpoint processes multiple PDF files through a configurable pipeline of operations. "
+ "Users provide files and a JSON configuration defining the sequence of operations to perform. "
+ "Input:PDF Output:PDF/ZIP Type:MIMO")
@RequestBody(
content =
@Content(
mediaType = "multipart/form-data",
examples =
@ExampleObject(
name = "Email Preparation Pipeline",
summary =
"Repair, sanitize, and compress PDFs for email",
value =
"{\n"
+ " \"name\": \"Prepare-pdfs-for-email\",\n"
+ " \"pipeline\": [\n"
+ " {\n"
+ " \"operation\": \"/api/v1/misc/repair\",\n"
+ " \"parameters\": {}\n"
+ " },\n"
+ " {\n"
+ " \"operation\": \"/api/v1/security/sanitize-pdf\",\n"
+ " \"parameters\": {\n"
+ " \"removeJavaScript\": true,\n"
+ " \"removeEmbeddedFiles\": false\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"operation\": \"/api/v1/misc/compress-pdf\",\n"
+ " \"parameters\": {\n"
+ " \"optimizeLevel\": 2\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ "}")))
public ResponseEntity<byte[]> handleData(@ModelAttribute HandleDataRequest request) public ResponseEntity<byte[]> handleData(@ModelAttribute HandleDataRequest request)
throws JsonMappingException, JsonProcessingException { throws JsonMappingException, JsonProcessingException {
MultipartFile[] files = request.getFileInput(); MultipartFile[] files = request.getFileInput();

View File

@ -71,10 +71,11 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest; import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest;
import stirling.software.common.service.ServerCertificateService;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.service.ServerCertificateService;
import stirling.software.common.util.ExceptionUtils; import stirling.software.common.util.ExceptionUtils;
import stirling.software.common.util.WebResponseUtils; import stirling.software.common.util.WebResponseUtils;
@ -140,9 +141,8 @@ public class CertSignController {
} }
} }
@AutoJobPostMapping( @AutoJobPostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/cert-sign")
consumes = MediaType.MULTIPART_FORM_DATA_VALUE, @StandardPdfResponse
value = "/cert-sign")
@Operation( @Operation(
summary = "Sign PDF with a Digital Certificate", summary = "Sign PDF with a Digital Certificate",
description = description =

View File

@ -60,6 +60,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.JsonDataResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -189,6 +190,7 @@ public class GetInfoOnPDF {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
@JsonDataResponse
@Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO") @Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO")
public ResponseEntity<byte[]> getPdfInfo(@ModelAttribute PDFFile request) throws IOException { public ResponseEntity<byte[]> getPdfInfo(@ModelAttribute PDFFile request) throws IOException {
MultipartFile inputFile = request.getFileInput(); MultipartFile inputFile = request.getFileInput();

View File

@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.security.AddPasswordRequest; import stirling.software.SPDF.model.api.security.AddPasswordRequest;
import stirling.software.SPDF.model.api.security.PDFPasswordRequest; import stirling.software.SPDF.model.api.security.PDFPasswordRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
@ -33,6 +34,7 @@ public class PasswordController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-password") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-password")
@StandardPdfResponse
@Operation( @Operation(
summary = "Remove password from a PDF file", summary = "Remove password from a PDF file",
description = description =
@ -59,6 +61,7 @@ public class PasswordController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-password") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-password")
@StandardPdfResponse
@Operation( @Operation(
summary = "Add password to a PDF file", summary = "Add password to a PDF file",
description = description =

View File

@ -29,6 +29,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.PDFText; import stirling.software.SPDF.model.PDFText;
import stirling.software.SPDF.model.api.security.ManualRedactPdfRequest; import stirling.software.SPDF.model.api.security.ManualRedactPdfRequest;
import stirling.software.SPDF.model.api.security.RedactPdfRequest; import stirling.software.SPDF.model.api.security.RedactPdfRequest;
@ -57,6 +58,7 @@ public class RedactController {
} }
@AutoJobPostMapping(value = "/redact", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/redact", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
operationId = "redactPdfManual", operationId = "redactPdfManual",
summary = "Redacts areas and pages in a PDF document", summary = "Redacts areas and pages in a PDF document",
@ -192,6 +194,7 @@ public class RedactController {
} }
@AutoJobPostMapping(value = "/auto-redact", consumes = "multipart/form-data") @AutoJobPostMapping(value = "/auto-redact", consumes = "multipart/form-data")
@StandardPdfResponse
@Operation( @Operation(
operationId = "redactPdfAuto", operationId = "redactPdfAuto",
summary = "Redacts listOfText in a PDF document", summary = "Redacts listOfText in a PDF document",

View File

@ -19,6 +19,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.model.api.PDFFile; import stirling.software.common.model.api.PDFFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -33,6 +34,7 @@ public class RemoveCertSignController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign")
@StandardPdfResponse
@Operation( @Operation(
summary = "Remove digital signature from PDF", summary = "Remove digital signature from PDF",
description = description =

View File

@ -33,6 +33,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.security.SanitizePdfRequest; import stirling.software.SPDF.model.api.security.SanitizePdfRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -47,6 +48,7 @@ public class SanitizeController {
private final CustomPDFDocumentFactory pdfDocumentFactory; private final CustomPDFDocumentFactory pdfDocumentFactory;
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf")
@StandardPdfResponse
@Operation( @Operation(
summary = "Sanitize a PDF file", summary = "Sanitize a PDF file",
description = description =

View File

@ -36,6 +36,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.JsonDataResponse;
import stirling.software.SPDF.model.api.security.SignatureValidationRequest; import stirling.software.SPDF.model.api.security.SignatureValidationRequest;
import stirling.software.SPDF.model.api.security.SignatureValidationResult; import stirling.software.SPDF.model.api.security.SignatureValidationResult;
import stirling.software.SPDF.service.CertificateValidationService; import stirling.software.SPDF.service.CertificateValidationService;
@ -64,6 +65,7 @@ public class ValidateSignatureController {
}); });
} }
@JsonDataResponse
@Operation( @Operation(
summary = "Validate PDF Digital Signature", summary = "Validate PDF Digital Signature",
description = description =

View File

@ -38,6 +38,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
import stirling.software.SPDF.model.api.security.AddWatermarkRequest; import stirling.software.SPDF.model.api.security.AddWatermarkRequest;
import stirling.software.common.annotations.AutoJobPostMapping; import stirling.software.common.annotations.AutoJobPostMapping;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
@ -65,6 +66,7 @@ public class WatermarkController {
} }
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-watermark") @AutoJobPostMapping(consumes = "multipart/form-data", value = "/add-watermark")
@StandardPdfResponse
@Operation( @Operation(
summary = "Add watermark to a PDF file", summary = "Add watermark to a PDF file",
description = description =

View File

@ -9,7 +9,6 @@ import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;

View File

@ -26,7 +26,8 @@ import stirling.software.common.configuration.InstallationPathConfig;
@Service @Service
@Slf4j @Slf4j
public class ServerCertificateService implements stirling.software.common.service.ServerCertificateService { public class ServerCertificateService
implements stirling.software.common.service.ServerCertificateService {
private static final String KEYSTORE_FILENAME = "server-certificate.p12"; private static final String KEYSTORE_FILENAME = "server-certificate.p12";
private static final String KEYSTORE_ALIAS = "stirling-pdf-server"; private static final String KEYSTORE_ALIAS = "stirling-pdf-server";
@ -212,5 +213,4 @@ public class ServerCertificateService implements stirling.software.common.servic
keyStore.store(fos, DEFAULT_PASSWORD.toCharArray()); keyStore.store(fos, DEFAULT_PASSWORD.toCharArray());
} }
} }
} }