我正在尝试使用 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 服务器时删除它
我使用 async/await 重写了您的代码,并且它按预期工作。但仍有一些问题需要解决。
(1) 当用户只有一台显示器时,
screenshots[1]
会出现索引越界错误。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);
}
});