File size: 4,834 Bytes
8e2959f b4297f5 8e2959f b4297f5 900310e b4297f5 900310e b4297f5 8e2959f b4297f5 8e2959f 900310e 8e2959f 900310e 8e2959f b4297f5 900310e 8e2959f 900310e b4297f5 8e2959f b4297f5 900310e b4297f5 8e2959f 900310e 8e2959f 900310e b4297f5 8e2959f b4297f5 8e2959f b4297f5 8e2959f b4297f5 8e2959f b4297f5 900310e b4297f5 900310e b4297f5 900310e b4297f5 900310e b4297f5 8e2959f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import puppeteer from 'puppeteer';
class ScreenshotService {
async generateScreenshot(htmlContent, options = {}) {
let browser = null;
try {
console.log('Starting Puppeteer browser...');
// 更适合容器环境的Puppeteer配置
browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--disable-web-security',
'--disable-features=TranslateUI',
'--disable-extensions',
'--disable-component-extensions-with-background-pages',
'--disable-default-apps',
'--mute-audio',
'--no-default-browser-check',
'--autoplay-policy=user-gesture-required',
'--disable-background-mode',
'--disable-plugins',
'--disable-translate',
'--disable-ipc-flooding-protection',
'--memory-pressure-off',
'--max_old_space_size=4096'
],
timeout: 30000,
protocolTimeout: 30000
});
console.log('Browser launched successfully');
const page = await browser.newPage();
console.log('New page created');
// PPT标准尺寸 (4:3 比例)
const pptWidth = 1000;
const pptHeight = 750;
// 设置页面视窗大小,添加足够的边距以避免裁切问题
await page.setViewport({
width: pptWidth + 100, // 添加边距
height: pptHeight + 100, // 添加边距
deviceScaleFactor: 2 // 高分辨率
});
console.log('Viewport set');
// 修改HTML内容,确保PPT容器居中且尺寸精确
const modifiedHtmlContent = htmlContent.replace(
'<div class="slide-container"',
`<div class="slide-container" style="width: ${pptWidth}px; height: ${pptHeight}px; position: absolute; left: 50px; top: 50px; margin: 0; transform: none; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"`
).replace(
'.viewport-container {',
`.viewport-container {
position: relative;
width: ${pptWidth + 100}px;
height: ${pptHeight + 100}px;
background-color: transparent;
display: block;`
);
// 设置HTML内容
await page.setContent(modifiedHtmlContent, {
waitUntil: 'domcontentloaded',
timeout: 10000
});
console.log('HTML content set');
// 等待渲染完成
await page.waitForTimeout(1000);
console.log('Taking screenshot...');
// 精确截取PPT区域
const screenshot = await page.screenshot({
type: 'jpeg',
quality: 90, // 提高质量
clip: {
x: 50,
y: 50,
width: pptWidth,
height: pptHeight
},
timeout: 10000
});
console.log('Screenshot taken successfully, size:', screenshot.length);
return screenshot;
} catch (error) {
console.error('Screenshot generation error:', error);
// 返回一个错误图片而不是抛出异常
return this.generateErrorImage(error.message);
} finally {
if (browser) {
try {
await browser.close();
console.log('Browser closed');
} catch (closeError) {
console.error('Error closing browser:', closeError);
}
}
}
}
// 生成错误提示图片 - 也使用精确的PPT尺寸
generateErrorImage(errorMessage = '截图生成失败') {
const pptWidth = 1000;
const pptHeight = 750;
const canvas = `
<svg width="${pptWidth}" height="${pptHeight}" xmlns="http://www.w3.org/2000/svg">
<rect width="${pptWidth}" height="${pptHeight}" fill="#f8f9fa"/>
<rect x="50" y="50" width="${pptWidth - 100}" height="${pptHeight - 100}" fill="white" stroke="#dee2e6" stroke-width="2"/>
<text x="${pptWidth / 2}" y="${pptHeight / 2 - 20}" text-anchor="middle" font-family="Arial" font-size="24" fill="#6c757d">
截图生成失败
</text>
<text x="${pptWidth / 2}" y="${pptHeight / 2 + 20}" text-anchor="middle" font-family="Arial" font-size="16" fill="#868e96">
${errorMessage}
</text>
</svg>
`;
return Buffer.from(canvas);
}
}
export default new ScreenshotService(); |