mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-12-18 20:04:17 +01:00
Merge a2c3399f2d into 3529849bca
This commit is contained in:
commit
c93774b02f
@ -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
|
||||
|
||||
|
||||
@ -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<byte[]> 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);
|
||||
}
|
||||
}
|
||||
@ -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<String, LongAdder> globalCounts = new ConcurrentHashMap<>();
|
||||
|
||||
// toolName -> userName -> count
|
||||
private final Map<String, Map<String, LongAdder>> 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<String, Long> getGlobalCounts() {
|
||||
return globalCounts.entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().sum()));
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 60_000)
|
||||
public void persistStats() {
|
||||
try {
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user