如何实现Node.js脚本定时监测文件夹并自动上传图片至API?
Node.js 实现方案
方法1:文件实时监听(高效推荐)
用chokidar库监听文件夹新增文件,无需定时轮询,响应更及时。
操作步骤:
- 安装依赖:
npm install chokidar axios
- 实现代码:
const chokidar = require('chokidar'); const axios = require('axios'); const fs = require('fs'); const path = require('path'); // 配置参数 const WATCH_DIR = './watch-folder'; // 目标监测文件夹 const UPLOAD_API = 'https://localhost:4200/images'; const PROCESSED_RECORD = './processed-files.json'; // 记录已上传文件,避免重复操作 // 初始化已处理文件集合 let processedFiles = new Set(); if (fs.existsSync(PROCESSED_RECORD)) { processedFiles = new Set(JSON.parse(fs.readFileSync(PROCESSED_RECORD, 'utf8'))); } // 保存已处理文件记录 const saveRecord = () => { fs.writeFileSync(PROCESSED_RECORD, JSON.stringify([...processedFiles])); }; // 文件上传逻辑 const uploadFile = async (filePath) => { try { const formData = new FormData(); formData.append('image', fs.createReadStream(filePath)); const response = await axios.post(UPLOAD_API, formData, { headers: { ...formData.getHeaders() } }); console.log(`文件 ${path.basename(filePath)} 上传成功:`, response.data); processedFiles.add(filePath); saveRecord(); } catch (err) { console.error(`文件 ${path.basename(filePath)} 上传失败:`, err.message); } }; // 启动文件夹监听 const watcher = chokidar.watch(WATCH_DIR, { ignored: /^\./, // 忽略隐藏文件 persistent: true, ignoreInitial: false // 启动时扫描已有文件(可选) }); // 监听新增文件事件 watcher.on('add', async (filePath) => { const ext = path.extname(filePath).toLowerCase(); // 仅处理图片格式 if (['.jpg', '.jpeg', '.png', '.gif'].includes(ext) && !processedFiles.has(filePath)) { await uploadFile(filePath); } }); watcher.on('error', (err) => console.error('监听出错:', err)); console.log(`已开始监测文件夹: ${WATCH_DIR}`);
方法2:定时轮询(轻量简单)
无需第三方库,定时扫描文件夹对比文件状态:
const fs = require('fs'); const path = require('path'); const axios = require('axios'); const WATCH_DIR = './watch-folder'; const UPLOAD_API = 'https://localhost:4200/images'; const CHECK_INTERVAL = 5000; // 5秒轮询一次 let processedFiles = new Set(); const scanAndUpload = async () => { try { const files = fs.readdirSync(WATCH_DIR).map(file => path.join(WATCH_DIR, file)); // 筛选新增图片文件 const newFiles = files.filter(file => { const ext = path.extname(file).toLowerCase(); return ['jpg', 'jpeg', 'png', 'gif'].includes(ext) && !processedFiles.has(file); }); for (const file of newFiles) { const formData = new FormData(); formData.append('image', fs.createReadStream(file)); await axios.post(UPLOAD_API, formData, { headers: formData.getHeaders() }); console.log(`文件 ${path.basename(file)} 上传成功`); processedFiles.add(file); } } catch (err) { console.error('轮询上传出错:', err.message); } }; // 初始扫描 scanAndUpload(); // 启动定时任务 setInterval(scanAndUpload, CHECK_INTERVAL); console.log(`已启动定时轮询,间隔 ${CHECK_INTERVAL/1000} 秒`);
PHP 实现方案
PHP本身是单请求运行模式,需结合Crontab定时任务实现定时扫描上传。
操作步骤:
- 编写上传脚本(
upload-images.php):
<?php // 配置参数 $watchDir = './watch-folder'; $uploadApi = 'https://localhost:4200/images'; $processedLog = './processed-files.log'; // 初始化已处理文件列表 $processedFiles = []; if (file_exists($processedLog)) { $processedFiles = file($processedLog, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } $processedFiles = array_flip($processedFiles); // 转关联数组提升查询效率 // 扫描文件夹 $files = scandir($watchDir); foreach ($files as $file) { $filePath = $watchDir . DIRECTORY_SEPARATOR . $file; // 跳过目录和隐藏文件 if (is_dir($filePath) || str_starts_with($file, '.')) { continue; } // 仅处理图片格式 $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) { continue; } // 跳过已处理文件 if (isset($processedFiles[$filePath])) { continue; } // 执行上传 $ch = curl_init(); $cfile = new CURLFile($filePath); $postData = ['image' => $cfile]; curl_setopt($ch, CURLOPT_URL, $uploadApi); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 本地测试可关闭,生产环境建议开启 $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpCode === 200) { echo "文件 {$file} 上传成功\n"; // 记录已处理文件 file_put_contents($processedLog, $filePath . PHP_EOL, FILE_APPEND); } else { echo "文件 {$file} 上传失败,HTTP状态码: {$httpCode}\n"; } curl_close($ch); } ?>
- 设置Crontab定时任务:
打开终端输入crontab -e,添加以下配置(示例为每5分钟执行一次,可按需调整):
*/5 * * * * php /绝对路径/upload-images.php >> /绝对路径/upload-log.log 2>&1
*/5 * * * *:代表每5分钟执行一次/绝对路径/upload-images.php:替换为脚本的实际绝对路径>> /绝对路径/upload-log.log 2>&1:将执行日志写入文件,便于排查问题
内容的提问来源于stack exchange,提问作者kate moss
相关产品推荐
相关产品推荐

