mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 11:23:10 +02:00
FileReadiness (#5985)
This commit is contained in:
+14
-4
@@ -66,7 +66,8 @@ public class ExtractImagesController {
|
||||
Set<Integer> processedImageHashes = new HashSet<>();
|
||||
|
||||
TempFile zipFile = new TempFile(tempFileManager, ".zip");
|
||||
try (ZipOutputStream zipStream = new ZipOutputStream(Files.newOutputStream(zipFile.getPath()));
|
||||
try (ZipOutputStream zipStream =
|
||||
new ZipOutputStream(Files.newOutputStream(zipFile.getPath()));
|
||||
PDDocument pdfDoc = pdfDocumentFactory.load(file)) {
|
||||
|
||||
zipStream.setLevel(Deflater.BEST_COMPRESSION);
|
||||
@@ -75,8 +76,12 @@ public class ExtractImagesController {
|
||||
for (int pageIndex = 0; pageIndex < totalPages; pageIndex++) {
|
||||
PDPage currentPage = pdfDoc.getPage(pageIndex);
|
||||
extractAndAddImagesToZip(
|
||||
currentPage, imageFormat, baseFilename, pageIndex + 1,
|
||||
processedImageHashes, zipStream);
|
||||
currentPage,
|
||||
imageFormat,
|
||||
baseFilename,
|
||||
pageIndex + 1,
|
||||
processedImageHashes,
|
||||
zipStream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
zipFile.close();
|
||||
@@ -119,7 +124,12 @@ public class ExtractImagesController {
|
||||
BufferedImage convertedImage = convertImageToFormat(sourceImage, imageFormat);
|
||||
|
||||
String imagePath =
|
||||
baseFilename + "_page_" + pageNumber + "_" + imageCount++ + "."
|
||||
baseFilename
|
||||
+ "_page_"
|
||||
+ pageNumber
|
||||
+ "_"
|
||||
+ imageCount++
|
||||
+ "."
|
||||
+ imageFormat;
|
||||
ByteArrayOutputStream imageBuffer = new ByteArrayOutputStream();
|
||||
ImageIO.write(convertedImage, imageFormat, imageBuffer);
|
||||
|
||||
+16
@@ -36,6 +36,7 @@ import stirling.software.SPDF.model.PipelineResult;
|
||||
import stirling.software.SPDF.service.ApiDocService;
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.service.PostHogService;
|
||||
import stirling.software.common.util.FileReadinessChecker;
|
||||
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
@@ -50,6 +51,7 @@ public class PipelineDirectoryProcessor {
|
||||
private final ApiDocService apiDocService;
|
||||
private final PipelineProcessor processor;
|
||||
private final PostHogService postHogService;
|
||||
private final FileReadinessChecker fileReadinessChecker;
|
||||
private final List<String> watchedFoldersDirs;
|
||||
private final String finishedFoldersDir;
|
||||
|
||||
@@ -62,11 +64,13 @@ public class PipelineDirectoryProcessor {
|
||||
ApiDocService apiDocService,
|
||||
PipelineProcessor processor,
|
||||
PostHogService postHogService,
|
||||
FileReadinessChecker fileReadinessChecker,
|
||||
RuntimePathConfig runtimePathConfig) {
|
||||
this.objectMapper = objectMapper;
|
||||
this.apiDocService = apiDocService;
|
||||
this.processor = processor;
|
||||
this.postHogService = postHogService;
|
||||
this.fileReadinessChecker = fileReadinessChecker;
|
||||
this.watchedFoldersDirs = runtimePathConfig.getPipelineWatchedFoldersPaths();
|
||||
this.finishedFoldersDir = runtimePathConfig.getPipelineFinishedFoldersPath();
|
||||
}
|
||||
@@ -269,6 +273,18 @@ public class PipelineDirectoryProcessor {
|
||||
}
|
||||
return isAllowed;
|
||||
})
|
||||
.filter(
|
||||
path -> {
|
||||
if (!fileReadinessChecker.isReady(path)) {
|
||||
log.info(
|
||||
"File '{}' is not yet ready for processing"
|
||||
+ " (still being written or locked),"
|
||||
+ " will retry on next scan cycle",
|
||||
path.getFileName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map(Path::toAbsolutePath)
|
||||
.filter(path -> true)
|
||||
.map(Path::toFile)
|
||||
|
||||
+2
-4
@@ -178,8 +178,7 @@ public class ReactRoutingController {
|
||||
String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl);
|
||||
|
||||
String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')";
|
||||
return
|
||||
"""
|
||||
return """
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -238,8 +237,7 @@ public class ReactRoutingController {
|
||||
String escapedBaseUrlJs = JavaScriptUtils.javaScriptEscape(baseUrl);
|
||||
|
||||
String serverUrl = "(window.location.origin + '" + escapedBaseUrlJs + "')";
|
||||
return
|
||||
"""
|
||||
return """
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
+4
-4
@@ -581,10 +581,10 @@ public class PdfJsonFallbackFontService {
|
||||
|
||||
Character.UnicodeScript script = Character.UnicodeScript.of(codePoint);
|
||||
return switch (script) {
|
||||
// HAN script is used by both Simplified and Traditional Chinese
|
||||
// Default to Simplified (mainland China, 1.4B speakers) as it's more common
|
||||
// Traditional Chinese PDFs are detected via font name aliases (MingLiU, PMingLiU,
|
||||
// etc.)
|
||||
// HAN script is used by both Simplified and Traditional Chinese
|
||||
// Default to Simplified (mainland China, 1.4B speakers) as it's more common
|
||||
// Traditional Chinese PDFs are detected via font name aliases (MingLiU, PMingLiU,
|
||||
// etc.)
|
||||
case HAN -> FALLBACK_FONT_CJK_ID;
|
||||
case HIRAGANA, KATAKANA -> FALLBACK_FONT_JP_ID;
|
||||
case HANGUL -> FALLBACK_FONT_KR_ID;
|
||||
|
||||
@@ -237,6 +237,14 @@ system:
|
||||
databaseBackup:
|
||||
cron: "0 0 0 * * ?" # Cron expression for automatic database backups "0 0 0 * * ?" daily at midnight
|
||||
|
||||
autoPipeline:
|
||||
outputFolder: "" # Output folder for processed pipeline files (leave empty for default)
|
||||
fileReadiness:
|
||||
enabled: true # Set to 'false' to skip all readiness checks and process files immediately (legacy behaviour)
|
||||
settleTimeMillis: 5000 # How long (ms) a file must be unmodified before it is considered fully written and stable. Default: 5000 (5 seconds)
|
||||
sizeCheckDelayMillis: 500 # Pause (ms) between two file-size reads used to detect active writes (Linux/macOS mid-copy detection). Default: 500
|
||||
allowedExtensions: [] # Optional extension allow-list (case-insensitive, without the leading dot). Empty list = accept all extensions. Example: ["pdf", "tiff"]
|
||||
|
||||
ui:
|
||||
appNameNavbar: "" # name displayed on the navigation bar
|
||||
logoStyle: classic # Options: 'classic' (default - classic S icon) or 'modern' (minimalist logo)
|
||||
|
||||
Reference in New Issue
Block a user