如何用NodeJS实现SFTP到SMB的流式文件传输(仅传3天内新文件)
问题描述
我尝试使用NodeJS脚本将SFTP服务器中的文件复制到SMB共享目录,但仅复制创建时间不超过3天的新文件。目前已完成代码基础框架,但不清楚如何将SFTP上的文件以流的形式读取,再流式写入SMB共享,以此避免因文件过大而使用本地存储进行下载再上传的循环。相关代码如下:
const path = require('path'); const sftp = require('ssh2-sftp-client'); const smb2 = require('smb2'); const config = require('./config'); function extractTimestamp(filename) {...} // works fine function calculateAgeFromTimestamp(timestamp) {...} // also works fine async function processFiles() { const sftpClient = new sftp(); const smbClient = new smb2(config.smb); try { await sftp.connect(config.sftp); console.log(`Listing remote SFTP source: ${config.sourceDir}`); const files = await sftp.list(config.sourceDir); if (files.length === 0) { console.log('No files found on SFTP.'); return; } for (const file of files) { const sourceFilePath = path.join(config.sourceDir, file.name); const destinationFilePath = config.smb.share + '\\' + file.name; const timestamp = extractTimestamp(file.name); const fileAgeDays = calculateAgeFromTimestamp(timestamp); if (fileAgeDays <= 3) { const exists = await new Promise((resolve, reject) => { smbClient.exists(destinationFilePath, (err, exists) => { if (err) { console.error('Error checking file existence on SMB:', err); reject(err); } else { resolve(exists); } }); }); if (!exists) { console.log('Found file to copy'); // !!!confusing stream code goes here } else { console.log('File already exists'); } } } } catch (error) { console.error('Error:', error); } finally { sftp.end(); smbClient.close(); } } processFiles();
请问是否可以通过某种包装器将SFTP的文件读取转换为流?
解决方案
完全可以实现流式传输,不需要本地存储中转。你可以利用ssh2-sftp-client提供的createReadStream方法读取SFTP文件流,再通过smb2的createWriteStream方法写入SMB共享,最后将两个流通过pipe连接起来即可。
把以下代码替换掉你标注的// !!!confusing stream code goes here部分:
// 用Promise包装流操作,确保异步流程等待复制完成 await new Promise((resolve, reject) => { // 创建SFTP读取流 const readStream = sftpClient.createReadStream(sourceFilePath); // 创建SMB写入流 const writeStream = smbClient.createWriteStream(destinationFilePath); // 处理流的错误 readStream.on('error', (err) => { console.error(`Failed to read SFTP file ${sourceFilePath}:`, err); reject(err); }); writeStream.on('error', (err) => { console.error(`Failed to write SMB file ${destinationFilePath}:`, err); reject(err); }); // 复制完成时触发 writeStream.on('finish', () => { console.log(`Successfully copied ${file.name} to SMB share`); resolve(); }); // 连接两个流,开始传输 readStream.pipe(writeStream); });
注意事项
- 确保
ssh2-sftp-client和smb2的版本支持流操作(当前主流版本都支持)。 - 流操作是异步的,必须用Promise包装并
await,否则循环会在文件复制完成前继续执行下一个文件,可能导致资源冲突。 - 错误处理要覆盖读写两个流的异常,避免单个文件复制失败导致整个脚本崩溃。
内容的提问来源于stack exchange,提问作者Dycey
相关产品推荐
相关产品推荐

