I am in the process of making an application for plotting running routes on a map and saving them to a mongodb database.
Currently, I am using puppeteer to visit a route in my application and passing the coordinates as a query string to the map component. Once the map is loaded, I take the screenshot, convert the returned Buffer into a base64 encoded string, save that to the database, and use the string to show the image on the frontend.
The middleware for the whole process looks like this:
exports.screenshotMap = async (req, res, next) => {
try {
const { lineFeatures } = req.body;
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
// open new browser
const page = await browser.newPage();
// create array of coordinates from geojson features
const coords = lineFeatures.map(line => line.geometry.coordinates);
// reduce to 2D array of [lat, lon] coords
const flattenedCoords = coords.reduce((accum, arr) => {
return accum.concat(arr);
}, []);
// Stringify coords before using them as query string
const coordsStr = JSON.stringify(flattenedCoords);
// goto page with map sending coordintaes along
await page.goto(`http://localhost:3000/test?coords=${coordsStr}`, {
waitUntil: 'networkidle0',
});
// wait for map to load, call onLoad callback, and set state to make the h1 visible
await page.waitForSelector('h1');
// wait one more second to make sure all tiles for the map are loaded. Longer routes can require significantly more tiles
await page.waitFor(1000);
const image = await page.screenshot({
type: 'jpeg',
quality: 100,
clip: {
x: 0,
y: 70,
width: 640,
height: 360,
},
omitBackground: true,
});
await browser.close();
// convert buffer to base64 string
const base64Image = await image.toString('base64');
// attach to request object to be used in the next middleware
req.image = base64Image;
next();
} catch (err) {
res.status(400).send(err);
}
};
This approach works, however I am wondering if there is a better way. I have read the storing the Buffer data is better for database memory purposes, as the base64 strings are very long. Would a better way be to save the Buffer data and convert it to an encoded string before sending it back to the client? Is there a recommended way for dealing with this kind of data? I am interested in hearing others thoughts and approaches.