第二次请求Node.js打开图片时出错

问题描述 投票:0回答:1

我正在尝试使用 Node 在所有显示器上捕获用户屏幕的屏幕截图,并将所有内容保存在一张图像中,到目前为止,如果我第一次调用它,一切都正常,但如果我尝试第二次调用它如果不重新启动服务器,则会出现错误,指出无法打开该文件。

因为我希望能够对屏幕截图提出多个请求,我能做什么? 我仍在与 Node 和 JS 集成,所以我不知道它如何运作得很好。

代码:

const express = require('express');
const app = express();
const port = 3000;
const fs = require('fs');


app.get('/', (req, res) => {
  hello = 'Hello World!';
  console.log(hello);
  res.send(hello);
});

app.get('/screenshot', (req, res) => {
  const screenshot = require('screenshot-desktop');
  const sharp = require('sharp');

  screenshot.listDisplays().then((displays) => {
    let screenshots = [];
    displays.forEach((display, i) => {
      const screenshotPath = `screenshot${i}.png`;
      screenshot({ screen: display.id }).then((imgBuffer) => { 
        fs.writeFile(screenshotPath, imgBuffer, (err) => { 
          if (err) throw err;
          console.log('Screenshot salvo!');
          screenshots.push(screenshotPath);
          if (screenshots.length === displays.length) {
            // Todas as screenshots foram salvas, agora junte-as
            Promise.all([
              sharp(screenshots[1]).metadata(),
              sharp(screenshots[0]).metadata()
            ]).then(([metadata1, metadata2]) => {
              sharp(screenshots[1])
                .extend({
                  top: 0,
                  bottom: 0,
                  left: 0,
                  right: metadata2.width,
                  background: { r: 0, g: 0, b: 0, alpha: 0 }
                })
                .composite([{ input: screenshots[0], left: metadata1.width, top: 0 }])
                .toBuffer()
                .then((buffer) => {
                  let base64Image = `data:image/png;base64,${buffer.toString('base64')}`;
                  res.send(base64Image);
                })
                .catch((err) => console.error(err));
            }).catch(err => console.error(err));
          }
        });
      }, (err) => {
        console.error(err);
      });
    });
  });
});

app.listen(port, () => {
  console.log(`Servidor rodando em http://localhost:${port}`);
});

我获取并记录错误:

Servidor rodando em http://localhost:3000
Screenshot salvo!
Screenshot salvo!
F:\Andre\sk-access-control-ai\facialRecog\server.js:23
          if (err) throw err;
                   ^

[Error: UNKNOWN: unknown error, open 'facialRecog\screenshot0.png'] {
  errno: -4094,
  code: 'UNKNOWN',
  syscall: 'open',
  path: 'facialRecog\\screenshot0.png'
}

Node.js v20.12.2

我尝试像这样创建它,但我不是替换文件,而是删除它并创建一个新文件,但这会给我错误

error eperm operation not permitted unlink
,说我无法删除文件,但我没有地方使用它,我只能在关闭 localhost:3000 服务器时删除它

javascript node.js screenshot
1个回答
0
投票

我使用 async/await 重写了您的代码,并且它按预期工作。但仍有一些问题需要解决。
(1) 当用户只有一台显示器时,

screenshots[1]
会出现索引越界错误。
(2) 当用户同时调用 api 时,带
screenshot${i}.png
的文件名会重复。

app.get('/screenshot', async (req, res) => {
  try {
    const displays = await screenshot.listDisplays();
    let screenshots = [];
    for (let i = 0; i < displays.length; i++) {
      const display = displays[i];
      const screenshotPath = `screenshot${i}.png`;
      const imgBuffer = await screenshot({ screen: display.id });
      fs.writeFileSync(screenshotPath, imgBuffer);
      console.log('Screenshot salvo!');
      screenshots.push(screenshotPath);
    }
    if (screenshots.length === displays.length) {
      // Todas as screenshots foram salvas, agora junte-as
      const [metadata1, metadata2] = await Promise.all([
        sharp(screenshots[1]).metadata(),
        sharp(screenshots[0]).metadata()
      ]);

      const buffer = await sharp(screenshots[1])
        .extend({
          top: 0,
          bottom: 0,
          left: 0,
          right: metadata2.width,
          background: { r: 0, g: 0, b: 0, alpha: 0 }
        })
        .composite([{ input: screenshots[0], left: metadata1.width, top: 0 }])
        .toBuffer();

      // unlink after merge image
      for (let i = 0; i < screenshots.length; i++) {
        fs.unlinkSync(screenshots[i]);
      }

      let base64Image = `data:image/png;base64,${buffer.toString('base64')}`;
      res.send(base64Image);
    }
    throw new Error('screenshots.length !== displays.length');
  } catch (err) {
    console.error(err);
    res.send(err.message);
  }
});
© www.soinside.com 2019 - 2024. All rights reserved.