Upload screenshotService.js
Browse files
backend/src/services/screenshotService.js
CHANGED
|
@@ -198,16 +198,24 @@ class ScreenshotService {
|
|
| 198 |
// 优化页面设置
|
| 199 |
await page.setRequestInterception(true);
|
| 200 |
page.on('request', (request) => {
|
| 201 |
-
//
|
| 202 |
const resourceType = request.resourceType();
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
request.continue();
|
| 206 |
-
} else if (resourceType === '
|
| 207 |
-
//
|
| 208 |
request.continue();
|
| 209 |
} else {
|
| 210 |
-
//
|
| 211 |
request.abort();
|
| 212 |
}
|
| 213 |
});
|
|
@@ -690,21 +698,55 @@ class ScreenshotService {
|
|
| 690 |
return document.fonts ? document.fonts.ready : Promise.resolve();
|
| 691 |
});
|
| 692 |
|
| 693 |
-
//
|
| 694 |
-
await page.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 695 |
|
| 696 |
// 优化内存使用
|
| 697 |
if (global.gc && Math.random() < 0.1) { // 随机触发GC,避免每次都执行
|
| 698 |
global.gc();
|
| 699 |
}
|
| 700 |
|
| 701 |
-
//
|
| 702 |
const screenshotOptions = {
|
| 703 |
type: format,
|
| 704 |
-
quality: format === 'jpeg' ? quality : undefined,
|
| 705 |
fullPage: false,
|
| 706 |
omitBackground: format === 'png', // PNG格式可以透明背景
|
| 707 |
-
clip: { x: 0, y: 0, width, height }
|
|
|
|
|
|
|
| 708 |
};
|
| 709 |
|
| 710 |
const screenshot = await page.screenshot(screenshotOptions);
|
|
|
|
| 198 |
// 优化页面设置
|
| 199 |
await page.setRequestInterception(true);
|
| 200 |
page.on('request', (request) => {
|
| 201 |
+
// 优化的资源拦截逻辑,确保SVG相关资源能够正确加载
|
| 202 |
const resourceType = request.resourceType();
|
| 203 |
+
const url = request.url();
|
| 204 |
+
|
| 205 |
+
// 允许SVG相关资源和基本资源
|
| 206 |
+
if (resourceType === 'document' ||
|
| 207 |
+
resourceType === 'stylesheet' ||
|
| 208 |
+
resourceType === 'script' ||
|
| 209 |
+
resourceType === 'font' ||
|
| 210 |
+
url.includes('svg') ||
|
| 211 |
+
url.includes('data:image/svg') ||
|
| 212 |
+
resourceType === 'image') {
|
| 213 |
request.continue();
|
| 214 |
+
} else if (resourceType === 'media' && !url.includes('ads')) {
|
| 215 |
+
// 允许非广告媒体资源
|
| 216 |
request.continue();
|
| 217 |
} else {
|
| 218 |
+
// 阻止其他不必要的资源
|
| 219 |
request.abort();
|
| 220 |
}
|
| 221 |
});
|
|
|
|
| 698 |
return document.fonts ? document.fonts.ready : Promise.resolve();
|
| 699 |
});
|
| 700 |
|
| 701 |
+
// 等待SVG元素完全加载和渲染
|
| 702 |
+
await page.evaluate(() => {
|
| 703 |
+
return new Promise(resolve => {
|
| 704 |
+
const svgs = document.querySelectorAll('svg');
|
| 705 |
+
if (svgs.length === 0) {
|
| 706 |
+
resolve();
|
| 707 |
+
return;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
let loadedCount = 0;
|
| 711 |
+
const checkComplete = () => {
|
| 712 |
+
loadedCount++;
|
| 713 |
+
if (loadedCount === svgs.length) resolve();
|
| 714 |
+
};
|
| 715 |
+
|
| 716 |
+
svgs.forEach(svg => {
|
| 717 |
+
if (svg.complete || svg.readyState === 'complete') {
|
| 718 |
+
checkComplete();
|
| 719 |
+
} else {
|
| 720 |
+
svg.addEventListener('load', checkComplete);
|
| 721 |
+
svg.addEventListener('error', checkComplete); // 处理加载错误
|
| 722 |
+
}
|
| 723 |
+
});
|
| 724 |
+
|
| 725 |
+
// 如果所有SVG都已完成,立即resolve
|
| 726 |
+
if (loadedCount === svgs.length) resolve();
|
| 727 |
+
|
| 728 |
+
// 超时保护,确保不会无限等待
|
| 729 |
+
setTimeout(resolve, 3000);
|
| 730 |
+
});
|
| 731 |
+
});
|
| 732 |
+
|
| 733 |
+
// 额外等待时间确保渲染完成
|
| 734 |
+
await page.waitForTimeout(500);
|
| 735 |
|
| 736 |
// 优化内存使用
|
| 737 |
if (global.gc && Math.random() < 0.1) { // 随机触发GC,避免每次都执行
|
| 738 |
global.gc();
|
| 739 |
}
|
| 740 |
|
| 741 |
+
// 优化的截图选项,提高矢量图形质量
|
| 742 |
const screenshotOptions = {
|
| 743 |
type: format,
|
| 744 |
+
quality: format === 'jpeg' ? Math.max(quality, 90) : undefined, // 提高JPEG质量
|
| 745 |
fullPage: false,
|
| 746 |
omitBackground: format === 'png', // PNG格式可以透明背景
|
| 747 |
+
clip: { x: 0, y: 0, width, height },
|
| 748 |
+
// 添加设备像素比以提高清晰度,特别是对矢量图形
|
| 749 |
+
deviceScaleFactor: 2
|
| 750 |
};
|
| 751 |
|
| 752 |
const screenshot = await page.screenshot(screenshotOptions);
|