从木偶师屏幕截图中保存图像数据的推荐方法是什么



我正在制作一个应用程序,用于在地图上绘制运行路线并将它们保存到mongodb数据库中。

目前,我正在使用木偶器访问应用程序中的路线,并将坐标作为查询字符串传递给地图组件。加载地图后,我截取屏幕截图,将返回的 Buffer 转换为 base64 编码字符串,将其保存到数据库中,然后使用该字符串在前端显示图像。

整个过程的中间件如下所示:

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);
  }
};

这种方法有效,但是我想知道是否有更好的方法。我已经读到存储缓冲区数据更适合数据库内存目的,因为 base64 字符串很长。更好的方法是保存 Buffer 数据并将其转换为编码字符串,然后再将其发送回客户端?是否有处理此类数据的推荐方法?我有兴趣听听别人的想法和方法。

我想出的解决方案是从屏幕截图返回的缓冲区保存到 S3 存储桶,然后将唯一标识符 url 存储到我的数据库中。

这是屏幕截图的中间件:

import puppeteer from 'puppeteer';
//import chromium from 'chrome-aws-lambda';
const takeMapImage = handler => async (req, res) => {
  try {
    const { lines } = req.body;
    // should work for most node projects
    const browser = await puppeteer.launch({
       args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });
    // if youre using lambda functions
    // const browser = await chromium.puppeteer.launch({
    //  executablePath: await chromium.executablePath,
    // args: chromium.args,
    // defaultViewport: chromium.defaultViewport,
    // headless: chromium.headless,
    // });
    // open new browser
    const page = await browser.newPage();
    const url = 'https://yourwebstieurl.com';
    await page.goto(
      `${url}`,
      {
        waitUntil: 'networkidle0',
      }
    );
    // provide some waiting time if needed
    await page.waitFor(1000);
   // image buffer returned from screenshot
    const imageBuffer = await page.screenshot({
      type: 'jpeg',
      quality: 100,
      clip: {
        x: 0,
        y: 0,
        width: 640,
        height: 360,
      },
      omitBackground: true,
    });

    // attach to request object to be used in the next middleware
    req.buffer = imageBuffer;
    next();
  } catch (err) {
    console.log(err);
    return res
      .status(422)
      .send({ message: 'there was an error taking picture' });
  }
};

然后是用于将图像保存到 s3 的中间件。您需要创建一个存储桶并获取凭证:

import AWS from 'aws-sdk';
import uuid from 'uuid/v1';
// create your s3instance with your credentials
const s3 = new AWS.S3({
  accessKeyId: process.env.S3_ACCESS_KEY_ID,
  secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
});
const saveImageToS3 = handler => async (req, res) => {
  try {
    // use user id as identifier in S3 bucket
    const { id } = req.user;
    const { buffer } = req;
    // s3 file name
    const key = `${id}/${uuid()}.jpeg`;
    const params = {
      Bucket: 'your-bucket-name',
      Key: key,
      Body: buffer,
      ContentEncoding: 'base64',
      ContentType: 'image/jpeg',
    };
    // upload to bucket
    const response = await s3.upload(params).promise();
    // pass url to next middleware to save to db
    req.image = response.Location;
    next();
  } catch (e) {
    console.log(e);
    return res.status(422).json({ message: 'user error saving image to s3' });
  }
};

最新更新