Spaces:
Running
Running
fix: use textOnlySizeMB for PDF render time estimation
Browse filesbase64 images don't increase Chromium PDF engine complexity.
The benchmark formula was calibrated on text-only HTML, so using
total HTML size (including base64) severely overestimates render time.
- Accept textOnlySizeMB from frontend (v2.0.5+)
- Fallback to total HTML size for backward compatibility with old plugins
- Use effectiveSizeMB (text-only) for timeout calculation, size limit check,
and large-file warning threshold
server.js
CHANGED
|
@@ -164,7 +164,7 @@ app.post('/api/generate_pdf', async (req, res) => {
|
|
| 164 |
let browser = null;
|
| 165 |
|
| 166 |
try {
|
| 167 |
-
const { html, showWatermark, imageCount, totalImageSizeMB, codeTheme } = req.body;
|
| 168 |
if (!html) {
|
| 169 |
return res.status(400).json({ error: 'Missing html content' });
|
| 170 |
}
|
|
@@ -194,14 +194,20 @@ app.post('/api/generate_pdf', async (req, res) => {
|
|
| 194 |
const imgCount = imageCount || 0;
|
| 195 |
const imgSizeMB = totalImageSizeMB || 0;
|
| 196 |
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
// HTML 大小硬性上限:超过 8 MB 时 Chromium PDF 引擎会崩溃
|
|
|
|
| 200 |
// Benchmark 验证:7.01 MB 需要 31 分钟,已超过用户可接受等待时间
|
| 201 |
// 建议用户减少内容量(如精简代码块、移除冗余样式)后重试
|
| 202 |
-
const
|
| 203 |
-
if (
|
| 204 |
-
const errorMsg = `HTML 内容过大 (${
|
| 205 |
console.log(`[PDF-GEN] [${getElapsed()}] ${errorMsg}`);
|
| 206 |
return res.status(413).json({ error: errorMsg });
|
| 207 |
}
|
|
@@ -227,9 +233,10 @@ app.post('/api/generate_pdf', async (req, res) => {
|
|
| 227 |
// Benchmark 数据揭示 PDF 渲染时间呈三次方增长:
|
| 228 |
// 0.82MB→8s, 1.64MB→16s, 3.28MB→85s, 4.92MB→>600s, 7.01MB→>1183s
|
| 229 |
// 拟合公式: pdfRenderMs ≈ 10*size³ + 10*size² + 2*size (秒)
|
|
|
|
| 230 |
// 超时 = 2× 安全系数, 上限 1800s (30 min)
|
| 231 |
const baseTimeout = 60000;
|
| 232 |
-
const s =
|
| 233 |
const pdfRenderMs = (10000 * s * s * s + 10000 * s * s + 2000 * s); // 预估 PDF 实际渲染时间 (ms)
|
| 234 |
const htmlExtraMs = Math.ceil(pdfRenderMs * 2); // 2x 安全系数
|
| 235 |
|
|
@@ -255,10 +262,10 @@ app.post('/api/generate_pdf', async (req, res) => {
|
|
| 255 |
// 动态计算 PDF 生成超时上限
|
| 256 |
const pdfTimeout = Math.min(120000 + extraMs / 5 + sizeExtraMs / 5 + htmlExtraMs, 3600000);
|
| 257 |
|
| 258 |
-
console.log(`[PDF-GEN] [${getElapsed()}] 动态超时: setContent=${(setContentTimeout / 1000).toFixed(0)}s, waitForNetworkIdle=${(networkTimeout / 1000).toFixed(0)}s, pdf=${(pdfTimeout / 1000).toFixed(0)}s (HTML=${htmlSizeMB}MB, 图片=${imgCount}张)`);
|
| 259 |
-
if (
|
| 260 |
const estMinutes = (pdfTimeout / 60000).toFixed(0);
|
| 261 |
-
console.log(`[PDF-GEN] [${getElapsed()}] ⚠️ 大文件预警: ${
|
| 262 |
}
|
| 263 |
console.log(`[PDF-GEN] [${getElapsed()}] 正在启动浏览器...`);
|
| 264 |
// protocolTimeout: 0 = 禁用 CDP 协议层超时
|
|
|
|
| 164 |
let browser = null;
|
| 165 |
|
| 166 |
try {
|
| 167 |
+
const { html, showWatermark, imageCount, totalImageSizeMB, codeTheme, textOnlySizeMB } = req.body;
|
| 168 |
if (!html) {
|
| 169 |
return res.status(400).json({ error: 'Missing html content' });
|
| 170 |
}
|
|
|
|
| 194 |
const imgCount = imageCount || 0;
|
| 195 |
const imgSizeMB = totalImageSizeMB || 0;
|
| 196 |
|
| 197 |
+
// 使用前端传来的纯文本 HTML 大小(扣除 base64 图片)做时间预估
|
| 198 |
+
// base64 图片不增加 Chromium PDF 引擎的渲染复杂度,benchmark 公式也是基于纯文本校准的
|
| 199 |
+
// 如果前端未提供(旧版本插件),回退到总大小(向后兼容)
|
| 200 |
+
const effectiveSizeMB = textOnlySizeMB != null ? textOnlySizeMB : htmlSizeMBNum;
|
| 201 |
+
|
| 202 |
+
console.log(`[PDF-GEN] [${getElapsed()}] 解析请求完成: HTML ${htmlSizeMB} MB (纯文本=${effectiveSizeMB.toFixed(2)} MB), 图片 ${imgCount} 张 (${imgSizeMB} MB)`);
|
| 203 |
|
| 204 |
// HTML 大小硬性上限:超过 8 MB 时 Chromium PDF 引擎会崩溃
|
| 205 |
+
// 使用纯文本大小判断(扣除 base64 图片),与前端保持一致
|
| 206 |
// Benchmark 验证:7.01 MB 需要 31 分钟,已超过用户可接受等待时间
|
| 207 |
// 建议用户减少内容量(如精简代码块、移除冗余样式)后重试
|
| 208 |
+
const MAX_TEXT_HTML_SIZE_MB = 8;
|
| 209 |
+
if (effectiveSizeMB > MAX_TEXT_HTML_SIZE_MB) {
|
| 210 |
+
const errorMsg = `HTML 内容过大 (纯文本=${effectiveSizeMB.toFixed(2)} MB,超过 ${MAX_TEXT_HTML_SIZE_MB} MB 上限),无法生成 PDF。建议:1) 精简对话内容;2) 移除大型代码块;3) 分批导出。`;
|
| 211 |
console.log(`[PDF-GEN] [${getElapsed()}] ${errorMsg}`);
|
| 212 |
return res.status(413).json({ error: errorMsg });
|
| 213 |
}
|
|
|
|
| 233 |
// Benchmark 数据揭示 PDF 渲染时间呈三次方增长:
|
| 234 |
// 0.82MB→8s, 1.64MB→16s, 3.28MB→85s, 4.92MB→>600s, 7.01MB→>1183s
|
| 235 |
// 拟合公式: pdfRenderMs ≈ 10*size³ + 10*size² + 2*size (秒)
|
| 236 |
+
// 使用纯文本大小(扣除 base64 图片),因为图片不增加渲染复杂度
|
| 237 |
// 超时 = 2× 安全系数, 上限 1800s (30 min)
|
| 238 |
const baseTimeout = 60000;
|
| 239 |
+
const s = effectiveSizeMB;
|
| 240 |
const pdfRenderMs = (10000 * s * s * s + 10000 * s * s + 2000 * s); // 预估 PDF 实际渲染时间 (ms)
|
| 241 |
const htmlExtraMs = Math.ceil(pdfRenderMs * 2); // 2x 安全系数
|
| 242 |
|
|
|
|
| 262 |
// 动态计算 PDF 生成超时上限
|
| 263 |
const pdfTimeout = Math.min(120000 + extraMs / 5 + sizeExtraMs / 5 + htmlExtraMs, 3600000);
|
| 264 |
|
| 265 |
+
console.log(`[PDF-GEN] [${getElapsed()}] 动态超时: setContent=${(setContentTimeout / 1000).toFixed(0)}s, waitForNetworkIdle=${(networkTimeout / 1000).toFixed(0)}s, pdf=${(pdfTimeout / 1000).toFixed(0)}s (HTML=${htmlSizeMB}MB, 纯文本=${effectiveSizeMB.toFixed(2)}MB, 图片=${imgCount}张)`);
|
| 266 |
+
if (effectiveSizeMB > 4) {
|
| 267 |
const estMinutes = (pdfTimeout / 60000).toFixed(0);
|
| 268 |
+
console.log(`[PDF-GEN] [${getElapsed()}] ⚠️ 大文件预警: 纯文本=${effectiveSizeMB.toFixed(2)} MB HTML 预计需要 ${estMinutes} 分钟`);
|
| 269 |
}
|
| 270 |
console.log(`[PDF-GEN] [${getElapsed()}] 正在启动浏览器...`);
|
| 271 |
// protocolTimeout: 0 = 禁用 CDP 协议层超时
|