问题
I'm using puppeteer to save and download images from markup & css sent to an express app by the browser. Express compiles the template, just inserting the POSTed markup into an html shell & gets the css locally (mounted on a docker volume).
When I render the html & css directly in chrome, all text and other elements display as expected. The screenshot that is saved, however, is missing the text.
When I leave out our styles, the text renders the same way in both local chrome & the image saved by puppeteer.
Are there styles set behind the scenes? Something else that could account for the difference?
EDIT: It now seems that it might be related to a race condition unhandled somewhere in my code. Without making changes, I was able to get the expected image, but only sometimes and I haven't yet been able to sort out what's different about those times.
Steps to reproduce
- Puppeteer version: 0.12.0
- Platform / OS version: docker/ubuntu
- Node.js version: 8
index.js:
app.post('/img', function (req, res) {
const puppeteer = require('puppeteer');
let css = [];
let stylesheets = [];
//
// separate out local stylesheets and read contents of the files
//
css = req.body.stylesheets.filter(sheet => {
return sheet.indexOf('https') === -1 && sheet.indexOf('http') === -1;
});
css = css.map(sheet => {
return fs.readFileSync(path.join(__dirname, sheet));
});
//
// separate out external stylesheets (bootstrap, etc)
//
stylesheets = req.body.stylesheets.filter(sheet => {
return sheet.indexOf('https') > -1 || sheet.indexOf('http') > -1;
});
//
// compile template with html & styles
//
app.render('img', {
stylesheets: stylesheets,
content: req.body.content,
css: css
}, function (err, html) {
console.log('html\n', html);
(async() => {
const browser = await puppeteer.launch({args: ['--no-sandbox']});
const page = await browser.newPage();
await page.setViewport({width: 1300, height: 1200});
//
// load html to chrome
//
try {
const loaded = page.waitForNavigation({
waitUntil: 'load'
});
await page.setContent(html);
await loaded
} catch(err) {
console.log(err);
res.status(err.status).send('There was an error loading the page.');
}
//
// save image
//
const filename = `${req.body.title}.png`;
const filepath = path.join(__dirname, 'img', filename);
try {
await page.screenshot({ path: filepath });
console.log(`${filename} saved`);
} catch(err) {
console.log(err);
res.status(err.status).send('There was a problem saving the image.');
}
res.status(201).send(filename);
})();
});
});
img.html (template):
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
{{#stylesheets}}
<link rel="stylesheet" type="text/css" href="{{{.}}}">
{{/stylesheets}}
{{#css}}
<style type="text/css">
{{{.}}}
</style>
{{/css}}
</head>
<body>
{{{content}}}
</body>
</html>
Expected
Without local styles:
With local styles:
Actual
Without local styles is as expected.
With local styles:
回答1:
It's likely that your docker image doesn't have the necessary fonts. There's a lot of open-source images out there (I maintain one here: https://github.com/joelgriffith/browserless) that try and alleviate common problems like this.
This is mostly its due to the base image not having the appropriate fonts.
来源:https://stackoverflow.com/questions/48324728/puppeteer-screenshot-has-missing-invisible-text