Upload public.js
Browse files- backend/src/routes/public.js +23 -33
backend/src/routes/public.js
CHANGED
@@ -477,11 +477,18 @@ router.get('/screenshot/:userId/:pptId/:slideIndex?', async (req, res, next) =>
|
|
477 |
|
478 |
// 🔥 关键修改:image端点现在直接返回SVG图片,不再返回截图工具页面
|
479 |
router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
|
|
|
480 |
try {
|
481 |
const { userId, pptId, slideIndex = 0 } = req.params;
|
482 |
-
const { format = 'svg', quality = 90, width: requestWidth, height: requestHeight } = req.query;
|
483 |
|
484 |
-
console.log(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
485 |
|
486 |
// Get PPT data
|
487 |
const fileName = `${pptId}.json`;
|
@@ -502,59 +509,42 @@ router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
|
|
502 |
|
503 |
if (!pptData) {
|
504 |
console.log(`❌ PPT not found: ${pptId}`);
|
505 |
-
// 返回404图片SVG
|
506 |
const notFoundSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
507 |
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
508 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">PPT Not Found</text>
|
509 |
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">PPT ${pptId} does not exist</text>
|
|
|
510 |
</svg>`;
|
511 |
|
512 |
-
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
513 |
-
res.setHeader('Cache-Control', 'no-cache');
|
514 |
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
515 |
return res.send(notFoundSvg);
|
516 |
}
|
517 |
|
518 |
const slideIdx = parseInt(slideIndex);
|
519 |
if (slideIdx >= pptData.slides.length || slideIdx < 0) {
|
520 |
console.log(`❌ Invalid slide index: ${slideIndex}`);
|
521 |
-
// 返回404幻灯片SVG
|
522 |
const invalidSlideSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
523 |
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
524 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">Invalid Slide</text>
|
525 |
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">Slide ${slideIndex} not found</text>
|
|
|
526 |
</svg>`;
|
527 |
|
528 |
-
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
529 |
-
res.setHeader('Cache-Control', 'no-cache');
|
530 |
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
531 |
return res.send(invalidSlideSvg);
|
532 |
}
|
533 |
|
534 |
console.log(`✅ Generating SVG for slide ${slideIdx}`);
|
535 |
|
536 |
-
//
|
|
|
537 |
const defaultWidth = pptData.viewportSize || 1000;
|
538 |
const defaultHeight = Math.ceil(defaultWidth * (pptData.viewportRatio || 0.5625));
|
539 |
-
const finalWidth = requestWidth ? parseInt(requestWidth) : defaultWidth;
|
540 |
-
const finalHeight = requestHeight ? parseInt(requestHeight) : defaultHeight;
|
541 |
|
542 |
-
// 生成PPT幻灯片的SVG图片
|
543 |
-
const slide = pptData.slides[slideIdx];
|
544 |
const svgContent = generateSlideSVG(slide, pptData, {
|
545 |
-
width:
|
546 |
-
height:
|
547 |
});
|
548 |
|
549 |
-
console.log(
|
550 |
-
|
551 |
-
// 设置正确的响应头,使其可以被其他网站作为图片引用
|
552 |
-
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
553 |
-
res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
|
554 |
-
res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域引用
|
555 |
-
res.setHeader('X-Generation-Time', '< 10ms');
|
556 |
-
res.setHeader('X-Content-Source', 'direct-svg-generation');
|
557 |
-
res.setHeader('Content-Disposition', 'inline'); // 确保浏览器内联显示图片
|
558 |
|
559 |
// 直接返回SVG图片内容
|
560 |
res.send(svgContent);
|
@@ -562,16 +552,17 @@ router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
|
|
562 |
} catch (error) {
|
563 |
console.error('❌ Image generation failed:', error);
|
564 |
|
565 |
-
//
|
|
|
|
|
|
|
566 |
const errorSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
567 |
<rect width="100%" height="100%" fill="#ffe6e6"/>
|
568 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#cc0000">Generation Error</text>
|
569 |
-
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#cc0000">Failed to generate image
|
|
|
570 |
</svg>`;
|
571 |
|
572 |
-
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
573 |
-
res.setHeader('Cache-Control', 'no-cache');
|
574 |
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
575 |
res.send(errorSvg);
|
576 |
}
|
577 |
});
|
@@ -594,8 +585,7 @@ router.get('/screenshot-data/:userId/:pptId/:slideIndex?', async (req, res, next
|
|
594 |
if (result) {
|
595 |
pptData = result.content;
|
596 |
break;
|
597 |
-
}
|
598 |
-
} catch (error) {
|
599 |
continue;
|
600 |
}
|
601 |
}
|
|
|
477 |
|
478 |
// 🔥 关键修改:image端点现在直接返回SVG图片,不再返回截图工具页面
|
479 |
router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
|
480 |
+
// 🚨 强制直接返回SVG图片 - 修复Hugging Face部署问题
|
481 |
try {
|
482 |
const { userId, pptId, slideIndex = 0 } = req.params;
|
|
|
483 |
|
484 |
+
console.log(`🔥 FORCE SVG GENERATION: userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}`);
|
485 |
+
|
486 |
+
// 立即设置SVG响应头,确保浏览器知道这是图片
|
487 |
+
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
488 |
+
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
|
489 |
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
490 |
+
res.setHeader('X-Force-Update', 'true');
|
491 |
+
res.setHeader('X-Timestamp', new Date().toISOString());
|
492 |
|
493 |
// Get PPT data
|
494 |
const fileName = `${pptId}.json`;
|
|
|
509 |
|
510 |
if (!pptData) {
|
511 |
console.log(`❌ PPT not found: ${pptId}`);
|
|
|
512 |
const notFoundSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
513 |
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
514 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">PPT Not Found</text>
|
515 |
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">PPT ${pptId} does not exist</text>
|
516 |
+
<text x="400" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#999">${new Date().toISOString()}</text>
|
517 |
</svg>`;
|
518 |
|
|
|
|
|
|
|
519 |
return res.send(notFoundSvg);
|
520 |
}
|
521 |
|
522 |
const slideIdx = parseInt(slideIndex);
|
523 |
if (slideIdx >= pptData.slides.length || slideIdx < 0) {
|
524 |
console.log(`❌ Invalid slide index: ${slideIndex}`);
|
|
|
525 |
const invalidSlideSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
526 |
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
527 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">Invalid Slide</text>
|
528 |
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">Slide ${slideIndex} not found</text>
|
529 |
+
<text x="400" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#999">${new Date().toISOString()}</text>
|
530 |
</svg>`;
|
531 |
|
|
|
|
|
|
|
532 |
return res.send(invalidSlideSvg);
|
533 |
}
|
534 |
|
535 |
console.log(`✅ Generating SVG for slide ${slideIdx}`);
|
536 |
|
537 |
+
// 生成PPT幻灯片的SVG图片
|
538 |
+
const slide = pptData.slides[slideIdx];
|
539 |
const defaultWidth = pptData.viewportSize || 1000;
|
540 |
const defaultHeight = Math.ceil(defaultWidth * (pptData.viewportRatio || 0.5625));
|
|
|
|
|
541 |
|
|
|
|
|
542 |
const svgContent = generateSlideSVG(slide, pptData, {
|
543 |
+
width: defaultWidth,
|
544 |
+
height: defaultHeight
|
545 |
});
|
546 |
|
547 |
+
console.log(`🎉 SVG generated successfully, returning image data`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
|
549 |
// 直接返回SVG图片内容
|
550 |
res.send(svgContent);
|
|
|
552 |
} catch (error) {
|
553 |
console.error('❌ Image generation failed:', error);
|
554 |
|
555 |
+
// 确保仍然返回SVG格式的错误信息
|
556 |
+
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
|
557 |
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
558 |
+
|
559 |
const errorSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
|
560 |
<rect width="100%" height="100%" fill="#ffe6e6"/>
|
561 |
<text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#cc0000">Generation Error</text>
|
562 |
+
<text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#cc0000">Failed to generate image</text>
|
563 |
+
<text x="400" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#999">${new Date().toISOString()}</text>
|
564 |
</svg>`;
|
565 |
|
|
|
|
|
|
|
566 |
res.send(errorSvg);
|
567 |
}
|
568 |
});
|
|
|
585 |
if (result) {
|
586 |
pptData = result.content;
|
587 |
break;
|
588 |
+
} catch (error) {
|
|
|
589 |
continue;
|
590 |
}
|
591 |
}
|