From 0c7bc5f792ad50e9ab2eb4f68aa88518143228a6 Mon Sep 17 00:00:00 2001 From: "Ervin, Nathan A" Date: Tue, 9 Dec 2025 13:32:31 -0600 Subject: [PATCH 1/3] Added Docker Guide Fix --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d9e0d5a41..752914376 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ For full installation options (including desktop and Kubernetes), see our [Docum - [**Homepage**](https://stirling.com) - [**API Docs**](https://registry.scalar.com/@stirlingpdf/apis/stirling-pdf-processing-api/) - [**Server Plan & Enterprise**](https://docs.stirlingpdf.com/Paid-Offerings) +- [**Docker Guide**](https://docs.stirlingpdf.com/Installation/Docker%20Guide/) ## Support From bec3892ea95ae57acacc262acdec95ba2152e4fc Mon Sep 17 00:00:00 2001 From: "Ervin, Nathan A" Date: Tue, 9 Dec 2025 13:40:58 -0600 Subject: [PATCH 2/3] Added file to increment for each use (Issue #4864) --- .../SPDF/service/UsageMetricsService.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 app/core/src/main/java/stirling/software/SPDF/service/UsageMetricsService.java diff --git a/app/core/src/main/java/stirling/software/SPDF/service/UsageMetricsService.java b/app/core/src/main/java/stirling/software/SPDF/service/UsageMetricsService.java new file mode 100644 index 000000000..fcaf60579 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/service/UsageMetricsService.java @@ -0,0 +1,66 @@ +package stirling.software.SPDF.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class UsageMetricsService { + + private final Map globalCounts = new ConcurrentHashMap<>(); + + // toolName -> userName -> count + private final Map> perUserCounts = new ConcurrentHashMap<>(); + + private final ObjectMapper mapper = new ObjectMapper(); + private final File statsFile = new File("configs/usage-stats.json"); + + public void recordUsage(String toolName, String username) { + // global + globalCounts.computeIfAbsent(toolName, k -> new LongAdder()).increment(); + + // per–user + if (username != null && !username.isBlank()) { + perUserCounts + .computeIfAbsent(toolName, k -> new ConcurrentHashMap<>()) + .computeIfAbsent(username, k -> new LongAdder()) + .increment(); + } + } + + // optional getters if you want to expose stats later + public Map getGlobalCounts() { + return globalCounts.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().sum())); + } + + @Scheduled(fixedDelay = 60_000) + public void persistStats() { + try { + Map dto = Map.of( + "global", getGlobalCounts(), + "perUser", perUserCounts.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> e.getValue().entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, x -> x.getValue().sum() + )) + )) + ); + statsFile.getParentFile().mkdirs(); + mapper.writerWithDefaultPrettyPrinter().writeValue(statsFile, dto); + } catch (IOException e) { + log.warn("Failed to persist usage stats", e); + } + } +} From a2c3399f2d8f95ce5eaad870b8ce9f58bf4402c6 Mon Sep 17 00:00:00 2001 From: "Ervin, Nathan A" Date: Tue, 9 Dec 2025 13:51:06 -0600 Subject: [PATCH 3/3] Added base for page enlargement down the road --- .../api/misc/ScalePagesController.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScalePagesController.java diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScalePagesController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScalePagesController.java new file mode 100644 index 000000000..2cd9b6f66 --- /dev/null +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ScalePagesController.java @@ -0,0 +1,41 @@ +package stirling.software.SPDF.controller.api.misc; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.*; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.service.ScalePagesService; +import stirling.software.SPDF.service.UsageMetricsService; + +import java.io.IOException; +import java.security.Principal; + +@RestController +@RequestMapping("/api/v1/misc") +@RequiredArgsConstructor +public class ScalePagesController { + + private final ScalePagesService scalePagesService; + private final UsageMetricsService usageMetricsService; + + @PostMapping("/scale-pages") + public ResponseEntity scalePages( + @RequestPart("file") MultipartFile file, + @RequestParam(defaultValue = "A4") String targetSize, + @RequestParam(defaultValue = "true") boolean keepAspectRatio, + Principal principal) throws IOException { + + usageMetricsService.recordUsage( + "scale-pages", + principal != null ? principal.getName() : null + ); + + byte[] output = scalePagesService.scalePages( + file.getBytes(), targetSize, keepAspectRatio); + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=scaled.pdf") + .contentType(MediaType.APPLICATION_PDF) + .body(output); + } +}