如何将摄像头人脸检测截图保存至JavaScript脚本同目录?
能否将网页捕获的人脸截图保存至JS文件所在的同一目录?
我用VS Code启动本地服务器,借助faceapi JavaScript库检测摄像头视频流里的人脸。程序会加载必要的人脸检测模型,在canvas上显示带检测框的实时视频,还做了个按钮可以捕获带人脸标记的截图并存为PNG文件,但现在图片默认存到浏览器的下载文件夹,想问能不能把截图存到JS文件所在的同一目录?
const screenshotButton = document.getElementById('screenshotButton'); Promise.all([ faceapi.nets.tinyFaceDetector.loadFromUri('/models'), faceapi.nets.faceLandmark68Net.loadFromUri('/models'), faceapi.nets.faceRecognitionNet.loadFromUri('/models'), faceapi.nets.faceExpressionNet.loadFromUri('/models') ]).then(startVideo); function startVideo() { navigator.getUserMedia( { video: {} }, stream => video.srcObject = stream, err => console.error(err) ); } video.addEventListener('play', () => { const canvas = faceapi.createCanvasFromMedia(video); document.body.append(canvas); const displaySize = { width: video.width, height: video.height }; faceapi.matchDimensions(canvas, displaySize); setInterval(async () => { const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions(); const resizedDetections = faceapi.resizeResults(detections, displaySize); canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); faceapi.draw.drawDetections(canvas, resizedDetections); }, 100); screenshotButton.addEventListener('click', async () => { const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions(); if (detections.length > 0) { const canvas = faceapi.createCanvasFromMedia(video); document.body.append(canvas); const displaySize = { width: video.width, height: video.height }; faceapi.matchDimensions(canvas, displaySize); const resizedDetections = faceapi.resizeResults(detections, displaySize); canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); faceapi.draw.drawDetections(canvas, resizedDetections); const context = canvas.getContext('2d'); context.drawImage(video, 0, 0, canvas.width, canvas.height); const dataURL = canvas.toDataURL('image/png'); const link = document.createElement('a'); link.download = `screenshot-${new Date().toISOString()}.png`; link.href = dataURL; document.body.appendChild(link); link.click(); document.body.removeChild(link); document.body.removeChild(canvas); // Remove the canvas after taking the screenshot } else { alert('No face detected in the video. Please position your face in front of the camera and try again.'); } }); });
核心结论
浏览器环境下的前端JavaScript无法直接自动将文件写入本地或服务器的任意目录,这是浏览器的安全机制限制,防止恶意网页随意操作用户文件系统。以下是两种可行的变通方案:
方案1:本地开发环境下用Node.js后端辅助保存
如果是自己本地开发测试,可以写一个简单的Node.js后端接口,前端把截图数据传给后端,由后端写入到JS文件所在的目录:
- 新建
server.js文件,用Express搭建服务:
const express = require('express'); const fs = require('fs'); const path = require('path'); const app = express(); app.use(express.json({ limit: '10mb' })); // 接收截图数据并保存 app.post('/save-screenshot', (req, res) => { const { base64Data, filename } = req.body; // 移除base64前缀并转成Buffer const buffer = Buffer.from(base64Data.replace(/^data:image\/png;base64,/, ''), 'base64'); // 保存到当前服务文件所在目录(可根据实际路径调整) const savePath = path.join(__dirname, filename); fs.writeFile(savePath, buffer, (err) => { if (err) return res.status(500).send('保存失败'); res.send('截图已保存到目标目录'); }); }); app.listen(3000, () => console.log('后端服务运行在http://localhost:3000'));
- 修改前端截图按钮的逻辑,替换原来的下载链接代码:
// 原link.click相关代码替换为: const base64Data = dataURL.replace(/^data:image\/png;base64,/, ''); fetch('http://localhost:3000/save-screenshot', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ base64Data, filename: `screenshot-${new Date().toISOString()}.png` }) }).then(res => res.text()).then(msg => alert(msg));
方案2:使用浏览器文件系统访问API(需用户手动确认)
现代浏览器支持文件系统访问API,允许用户手动选择保存目录,你可以引导用户选择JS文件所在的目录后保存:
修改前端截图逻辑:
// 原link.click相关代码替换为: const blob = await fetch(dataURL).then(res => res.blob()); // 弹出保存文件选择框 const handle = await window.showSaveFilePicker({ suggestedName: `screenshot-${new Date().toISOString()}.png`, types: [{ description: 'PNG图片', accept: { 'image/png': ['.png'] } }] }); // 写入文件 const writable = await handle.createWritable(); await writable.write(blob); await writable.close(); alert('截图保存成功');
注意:这个API必须由用户主动触发(比如点击按钮),且需要用户手动选择保存目录,无法自动直接写入目标目录,这是浏览器的安全要求。
内容的提问来源于stack exchange,提问作者Ken Robertson
相关产品推荐
相关产品推荐

