mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-07-28 13:47:43 +02:00
Merge branch 'main' into bug/remember-me
This commit is contained in:
commit
e7356a1d38
@ -210,7 +210,7 @@ Stirling-PDF currently supports 36 languages!
|
||||
| Spanish (Español) (es_ES) |  |
|
||||
| Swedish (Svenska) (sv_SE) |  |
|
||||
| Thai (ไทย) (th_TH) |  |
|
||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||
| Turkish (Türkçe) (tr_TR) |  |
|
||||
| Ukrainian (Українська) (uk_UA) |  |
|
||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||
|
@ -47,6 +47,7 @@ public class ApplicationProperties {
|
||||
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
||||
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
||||
private AutoPipeline autoPipeline = new AutoPipeline();
|
||||
private ProcessExecutor processExecutor = new ProcessExecutor();
|
||||
|
||||
@Data
|
||||
public static class AutoPipeline {
|
||||
@ -309,4 +310,98 @@ public class ApplicationProperties {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ProcessExecutor {
|
||||
private SessionLimit sessionLimit = new SessionLimit();
|
||||
private TimeoutMinutes timeoutMinutes = new TimeoutMinutes();
|
||||
|
||||
@Data
|
||||
public static class SessionLimit {
|
||||
private int libreOfficeSessionLimit;
|
||||
private int pdfToHtmlSessionLimit;
|
||||
private int ocrMyPdfSessionLimit;
|
||||
private int pythonOpenCvSessionLimit;
|
||||
private int ghostScriptSessionLimit;
|
||||
private int weasyPrintSessionLimit;
|
||||
private int installAppSessionLimit;
|
||||
private int calibreSessionLimit;
|
||||
|
||||
public int getLibreOfficeSessionLimit() {
|
||||
return libreOfficeSessionLimit > 0 ? libreOfficeSessionLimit : 1;
|
||||
}
|
||||
|
||||
public int getPdfToHtmlSessionLimit() {
|
||||
return pdfToHtmlSessionLimit > 0 ? pdfToHtmlSessionLimit : 1;
|
||||
}
|
||||
|
||||
public int getOcrMyPdfSessionLimit() {
|
||||
return ocrMyPdfSessionLimit > 0 ? ocrMyPdfSessionLimit : 2;
|
||||
}
|
||||
|
||||
public int getPythonOpenCvSessionLimit() {
|
||||
return pythonOpenCvSessionLimit > 0 ? pythonOpenCvSessionLimit : 8;
|
||||
}
|
||||
|
||||
public int getGhostScriptSessionLimit() {
|
||||
return ghostScriptSessionLimit > 0 ? ghostScriptSessionLimit : 16;
|
||||
}
|
||||
|
||||
public int getWeasyPrintSessionLimit() {
|
||||
return weasyPrintSessionLimit > 0 ? weasyPrintSessionLimit : 16;
|
||||
}
|
||||
|
||||
public int getInstallAppSessionLimit() {
|
||||
return installAppSessionLimit > 0 ? installAppSessionLimit : 1;
|
||||
}
|
||||
|
||||
public int getCalibreSessionLimit() {
|
||||
return calibreSessionLimit > 0 ? calibreSessionLimit : 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TimeoutMinutes {
|
||||
private long libreOfficeTimeoutMinutes;
|
||||
private long pdfToHtmlTimeoutMinutes;
|
||||
private long ocrMyPdfTimeoutMinutes;
|
||||
private long pythonOpenCvTimeoutMinutes;
|
||||
private long ghostScriptTimeoutMinutes;
|
||||
private long weasyPrintTimeoutMinutes;
|
||||
private long installAppTimeoutMinutes;
|
||||
private long calibreTimeoutMinutes;
|
||||
|
||||
public long getLibreOfficeTimeoutMinutes() {
|
||||
return libreOfficeTimeoutMinutes > 0 ? libreOfficeTimeoutMinutes : 30;
|
||||
}
|
||||
|
||||
public long getPdfToHtmlTimeoutMinutes() {
|
||||
return pdfToHtmlTimeoutMinutes > 0 ? pdfToHtmlTimeoutMinutes : 20;
|
||||
}
|
||||
|
||||
public long getOcrMyPdfTimeoutMinutes() {
|
||||
return ocrMyPdfTimeoutMinutes > 0 ? ocrMyPdfTimeoutMinutes : 30;
|
||||
}
|
||||
|
||||
public long getPythonOpenCvTimeoutMinutes() {
|
||||
return pythonOpenCvTimeoutMinutes > 0 ? pythonOpenCvTimeoutMinutes : 30;
|
||||
}
|
||||
|
||||
public long getGhostScriptTimeoutMinutes() {
|
||||
return ghostScriptTimeoutMinutes > 0 ? ghostScriptTimeoutMinutes : 30;
|
||||
}
|
||||
|
||||
public long getWeasyPrintTimeoutMinutes() {
|
||||
return weasyPrintTimeoutMinutes > 0 ? weasyPrintTimeoutMinutes : 30;
|
||||
}
|
||||
|
||||
public long getInstallAppTimeoutMinutes() {
|
||||
return installAppTimeoutMinutes > 0 ? installAppTimeoutMinutes : 60;
|
||||
}
|
||||
|
||||
public long getCalibreTimeoutMinutes() {
|
||||
return calibreTimeoutMinutes > 0 ? calibreTimeoutMinutes : 30;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,14 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.github.pixee.security.BoundedLineReader;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
public class ProcessExecutor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);
|
||||
|
||||
private static ApplicationProperties applicationProperties = new ApplicationProperties();
|
||||
|
||||
public enum Processes {
|
||||
LIBRE_OFFICE,
|
||||
PDFTOHTML,
|
||||
@ -45,26 +49,90 @@ public class ProcessExecutor {
|
||||
key -> {
|
||||
int semaphoreLimit =
|
||||
switch (key) {
|
||||
case LIBRE_OFFICE -> 1;
|
||||
case PDFTOHTML -> 1;
|
||||
case OCR_MY_PDF -> 2;
|
||||
case PYTHON_OPENCV -> 8;
|
||||
case GHOSTSCRIPT -> 16;
|
||||
case WEASYPRINT -> 16;
|
||||
case INSTALL_APP -> 1;
|
||||
case CALIBRE -> 1;
|
||||
case LIBRE_OFFICE ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getLibreOfficeSessionLimit();
|
||||
case PDFTOHTML ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getPdfToHtmlSessionLimit();
|
||||
case OCR_MY_PDF ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getOcrMyPdfSessionLimit();
|
||||
case PYTHON_OPENCV ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getPythonOpenCvSessionLimit();
|
||||
case GHOSTSCRIPT ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getGhostScriptSessionLimit();
|
||||
case WEASYPRINT ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getWeasyPrintSessionLimit();
|
||||
case INSTALL_APP ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getInstallAppSessionLimit();
|
||||
case CALIBRE ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getSessionLimit()
|
||||
.getCalibreSessionLimit();
|
||||
};
|
||||
|
||||
long timeoutMinutes =
|
||||
switch (key) {
|
||||
case LIBRE_OFFICE -> 30;
|
||||
case PDFTOHTML -> 20;
|
||||
case OCR_MY_PDF -> 30;
|
||||
case PYTHON_OPENCV -> 30;
|
||||
case GHOSTSCRIPT -> 30;
|
||||
case WEASYPRINT -> 30;
|
||||
case INSTALL_APP -> 60;
|
||||
case CALIBRE -> 30;
|
||||
case LIBRE_OFFICE ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getLibreOfficeTimeoutMinutes();
|
||||
case PDFTOHTML ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getPdfToHtmlTimeoutMinutes();
|
||||
case OCR_MY_PDF ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getOcrMyPdfTimeoutMinutes();
|
||||
case PYTHON_OPENCV ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getPythonOpenCvTimeoutMinutes();
|
||||
case GHOSTSCRIPT ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getGhostScriptTimeoutMinutes();
|
||||
case WEASYPRINT ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getWeasyPrintTimeoutMinutes();
|
||||
case INSTALL_APP ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getInstallAppTimeoutMinutes();
|
||||
case CALIBRE ->
|
||||
applicationProperties
|
||||
.getProcessExecutor()
|
||||
.getTimeoutMinutes()
|
||||
.getCalibreTimeoutMinutes();
|
||||
};
|
||||
return new ProcessExecutor(semaphoreLimit, liveUpdates, timeoutMinutes);
|
||||
});
|
||||
|
@ -50,4 +50,4 @@ springdoc.swagger-ui.url=/v1/api-docs
|
||||
|
||||
|
||||
posthog.api.key=phc_fiR65u5j6qmXTYL56MNrLZSWqLaDW74OrZH0Insd2xq
|
||||
posthog.host=https://eu.i.posthog.com
|
||||
posthog.host=https://eu.i.posthog.com
|
||||
|
@ -79,8 +79,8 @@ info=資訊
|
||||
pro=專業版
|
||||
page=頁面
|
||||
pages=頁面
|
||||
loading=Loading...
|
||||
addToDoc=Add to Document
|
||||
loading=載入中...
|
||||
addToDoc=新增至文件
|
||||
|
||||
legal.privacy=隱私權政策
|
||||
legal.terms=使用條款
|
||||
@ -140,7 +140,7 @@ navbar.darkmode=深色模式
|
||||
navbar.language=語言
|
||||
navbar.settings=設定
|
||||
navbar.allTools=工具
|
||||
navbar.multiTool=多功能工具
|
||||
navbar.multiTool=複合工具
|
||||
navbar.sections.organize=整理
|
||||
navbar.sections.convertTo=轉換為 PDF
|
||||
navbar.sections.convertFrom=從 PDF 轉換
|
||||
@ -246,7 +246,7 @@ database.fileNullOrEmpty=檔案不得為空或空白
|
||||
database.failedImportFile=匯入檔案失敗
|
||||
|
||||
session.expired=您的工作階段已過期。請重新整理頁面並再試一次。
|
||||
session.refreshPage=Refresh Page
|
||||
session.refreshPage=重新整理頁面
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@ -751,7 +751,7 @@ certSign.showSig=顯示簽章
|
||||
certSign.reason=原因
|
||||
certSign.location=位置
|
||||
certSign.name=名稱
|
||||
certSign.showLogo=Show Logo
|
||||
certSign.showLogo=顯示 Logo
|
||||
certSign.submit=簽章 PDF
|
||||
|
||||
|
||||
@ -786,9 +786,9 @@ compare.highlightColor.2=標示顏色 2:
|
||||
compare.document.1=文件 1
|
||||
compare.document.2=文件 2
|
||||
compare.submit=比較
|
||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
||||
compare.complex.message=選擇的檔案大小太大(其中一個或兩者皆是),可能會影響比較的精確度
|
||||
compare.large.file.message=選擇的檔案大小超出系統限制(其中一個或兩者皆是),無法處理
|
||||
compare.no.text.message=選擇的 PDF 檔案未包含文字(其中一個或兩者皆是)。請選擇含有文字的 PDF 進行比較
|
||||
|
||||
#BookToPDF
|
||||
BookToPDF.title=電子書和漫畫轉 PDF
|
||||
@ -805,17 +805,17 @@ PDFToBook.submit=轉換
|
||||
|
||||
#sign
|
||||
sign.title=簽章
|
||||
sign.header=簽章 PDF
|
||||
sign.header=簽署 PDF
|
||||
sign.upload=上傳影像
|
||||
sign.draw=繪製簽章
|
||||
sign.text=文字輸入
|
||||
sign.clear=清除
|
||||
sign.add=新增
|
||||
sign.saved=Saved Signatures
|
||||
sign.save=Save Signature
|
||||
sign.personalSigs=Personal Signatures
|
||||
sign.sharedSigs=Shared Signatures
|
||||
sign.noSavedSigs=No saved signatures found
|
||||
sign.saved=已儲存的簽章
|
||||
sign.save=儲存簽章
|
||||
sign.personalSigs=個人簽章
|
||||
sign.sharedSigs=共用簽章
|
||||
sign.noSavedSigs=尚未儲存任何簽章
|
||||
|
||||
|
||||
#repair
|
||||
|
@ -102,3 +102,22 @@ metrics:
|
||||
AutomaticallyGenerated:
|
||||
key: example
|
||||
UUID: example
|
||||
|
||||
processExecutor:
|
||||
sessionLimit: # Process executor instances limits
|
||||
libreOfficeSessionLimit: 1
|
||||
pdfToHtmlSessionLimit: 1
|
||||
ocrMyPdfSessionLimit: 2
|
||||
pythonOpenCvSessionLimit: 8
|
||||
ghostScriptSessionLimit: 16
|
||||
weasyPrintSessionLimit: 16
|
||||
installAppSessionLimit: 1
|
||||
calibreSessionLimit: 1
|
||||
timeoutMinutes: # Process executor timeout in minutes
|
||||
libreOfficetimeoutMinutes: 30
|
||||
pdfToHtmltimeoutMinutes: 20
|
||||
pythonOpenCvtimeoutMinutes: 30
|
||||
ghostScripttimeoutMinutes: 30
|
||||
weasyPrinttimeoutMinutes: 30
|
||||
installApptimeoutMinutes: 60
|
||||
calibretimeoutMinutes: 30
|
||||
|
@ -21,27 +21,55 @@ async function displayFiles(files) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const pageCount = await getPDFPageCount(files[i]);
|
||||
const pageLabel = pageCount === 1 ? pageTranslation : pagesTranslation;
|
||||
|
||||
// Create list item
|
||||
const item = document.createElement("li");
|
||||
item.className = "list-group-item";
|
||||
item.innerHTML = `
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<div class="filename">${files[i].name}</div>
|
||||
<div class="page-info">
|
||||
<span class="page-count">${pageCount} ${pageLabel}</span>
|
||||
</div>
|
||||
<div class="arrows d-flex">
|
||||
<button class="btn btn-secondary move-up"><span>↑</span></button>
|
||||
<button class="btn btn-secondary move-down"><span>↓</span></button>
|
||||
<button class="btn btn-danger remove-file"><span>×</span></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Create filename div and set textContent to sanitize
|
||||
const fileNameDiv = document.createElement("div");
|
||||
fileNameDiv.className = "filename";
|
||||
fileNameDiv.textContent = files[i].name;
|
||||
|
||||
// Create page info div and set textContent to sanitize
|
||||
const pageInfoDiv = document.createElement("div");
|
||||
pageInfoDiv.className = "page-info";
|
||||
const pageCountSpan = document.createElement("span");
|
||||
pageCountSpan.className = "page-count";
|
||||
pageCountSpan.textContent = `${pageCount} ${pageLabel}`;
|
||||
pageInfoDiv.appendChild(pageCountSpan);
|
||||
|
||||
// Create arrows div with buttons
|
||||
const arrowsDiv = document.createElement("div");
|
||||
arrowsDiv.className = "arrows d-flex";
|
||||
|
||||
const moveUpButton = document.createElement("button");
|
||||
moveUpButton.className = "btn btn-secondary move-up";
|
||||
moveUpButton.innerHTML = "<span>↑</span>";
|
||||
|
||||
const moveDownButton = document.createElement("button");
|
||||
moveDownButton.className = "btn btn-secondary move-down";
|
||||
moveDownButton.innerHTML = "<span>↓</span>";
|
||||
|
||||
const removeButton = document.createElement("button");
|
||||
removeButton.className = "btn btn-danger remove-file";
|
||||
removeButton.innerHTML = "<span>×</span>";
|
||||
|
||||
arrowsDiv.append(moveUpButton, moveDownButton, removeButton);
|
||||
|
||||
// Append elements to item and then to list
|
||||
const itemContainer = document.createElement("div");
|
||||
itemContainer.className = "d-flex justify-content-between align-items-center w-100";
|
||||
itemContainer.append(fileNameDiv, pageInfoDiv, arrowsDiv);
|
||||
|
||||
item.appendChild(itemContainer);
|
||||
list.appendChild(item);
|
||||
}
|
||||
|
||||
attachMoveButtons();
|
||||
}
|
||||
|
||||
|
||||
async function getPDFPageCount(file) {
|
||||
const blobUrl = URL.createObjectURL(file);
|
||||
const pdf = await pdfjsLib.getDocument(blobUrl).promise;
|
||||
|
Loading…
Reference in New Issue
Block a user