nodejs从sftp下载文件
nodejs download files from sftp
我需要从 sftp
下载一些 .txt.pgp
文件。我试过 npm ssh2
、ssh2-sftp-client
和 node-ssh
都没有成功。
到目前为止我得到的最接近的是使用 sftp.readdir
(ssh2
) 或 sftp.list
(ssh2-sftp-client
) 的远程文件夹中的文件列表。
我试过 pipe
、fs.createWriteStream
和 sftp.fastGet
,但我的本地机器上没有保存文件。
const conn = new Client();
conn.on('ready', () => {
console.log('Client :: ready');
conn.sftp((err, sftp) => {
if (err) throw err;
sftp.readdir('out', (err, list) => {
if (err) throw err;
list.forEach(item => {
console.log(item.filename);
const fileName = item.filename;
sftp.fastGet(fileName, fileName, {}, downloadError => {
if(downloadError) throw downloadError;
console.log("Succesfully uploaded");
});
})
conn.end();
});
});
}).connect(config);
或
const Client = require('ssh2-sftp-client');
const sftp = new Client();
sftp.connect(config).then(() => {
return sftp.list('out');
})
.then(files => {
// console.log(files);
if (files.length > 0) {
console.log('got list of files!');
}
files.map(file => {
const fileName = file.name;
sftp.get(fileName)
.then(() => {
fs.writeFile(fileName);
});
})
})
.then(() => {
sftp.end();
}).catch((err) => {
console.log(err);
});
关于您的第一次尝试(使用 ssh2
模块),我发现了三个问题:
- 您在一系列前面的异步函数之外调用
conn.end()
,这几乎肯定会导致 SSH 会话在您完成文件下载之前关闭。
- 您没有为
sftp.fastGet()
函数提供远程文件的正确路径。在代码的前面,您使用远程目录参数 'out'
调用 sftp.readdir()
,其中 returns 是相对于远程目录的文件列表。 (要点是:您需要将远程目录添加到文件名之前以创建正确限定的路径。)
- 您没有处理流事件
error
,所以我怀疑您没有收到有用的错误消息来帮助解决问题。
试试这样的东西:
const Client = require('ssh2').Client;
const conn = new Client();
const sshOpt = someFunctionThatPopulatesSshOptions();
const remoteDir = 'out';
conn.on('ready', () => {
conn.sftp((err, sftp) => {
if (err) throw err;
sftp.readdir(remoteDir, (err, list) => {
if (err) throw err;
let count = list.length;
list.forEach(item => {
let remoteFile = remoteDir + '/' + item.filename;
let localFile = '/tmp/' + item.filename;
console.log('Downloading ' + remoteFile);
sftp.fastGet(remoteFile, localFile, (err) => {
if (err) throw err;
console.log('Downloaded to ' + localFile);
count--;
if (count <= 0) {
conn.end();
}
});
});
});
});
});
conn.on('error', (err) => {
console.error('SSH connection stream problem');
throw err;
});
conn.connect(sshOpt);
这应该可以解决我提到的所有问题。具体来说:
- 我们正在使用
count
变量来确保 SSH 会话仅在所有文件下载完成后关闭。 (我知道它不漂亮。)
- 我们正在为所有远程文件下载添加
remoteDir
。
- 我们正在
conn
流中监听 error
事件。
我需要从 sftp
下载一些 .txt.pgp
文件。我试过 npm ssh2
、ssh2-sftp-client
和 node-ssh
都没有成功。
到目前为止我得到的最接近的是使用 sftp.readdir
(ssh2
) 或 sftp.list
(ssh2-sftp-client
) 的远程文件夹中的文件列表。
我试过 pipe
、fs.createWriteStream
和 sftp.fastGet
,但我的本地机器上没有保存文件。
const conn = new Client();
conn.on('ready', () => {
console.log('Client :: ready');
conn.sftp((err, sftp) => {
if (err) throw err;
sftp.readdir('out', (err, list) => {
if (err) throw err;
list.forEach(item => {
console.log(item.filename);
const fileName = item.filename;
sftp.fastGet(fileName, fileName, {}, downloadError => {
if(downloadError) throw downloadError;
console.log("Succesfully uploaded");
});
})
conn.end();
});
});
}).connect(config);
或
const Client = require('ssh2-sftp-client');
const sftp = new Client();
sftp.connect(config).then(() => {
return sftp.list('out');
})
.then(files => {
// console.log(files);
if (files.length > 0) {
console.log('got list of files!');
}
files.map(file => {
const fileName = file.name;
sftp.get(fileName)
.then(() => {
fs.writeFile(fileName);
});
})
})
.then(() => {
sftp.end();
}).catch((err) => {
console.log(err);
});
关于您的第一次尝试(使用 ssh2
模块),我发现了三个问题:
- 您在一系列前面的异步函数之外调用
conn.end()
,这几乎肯定会导致 SSH 会话在您完成文件下载之前关闭。 - 您没有为
sftp.fastGet()
函数提供远程文件的正确路径。在代码的前面,您使用远程目录参数'out'
调用sftp.readdir()
,其中 returns 是相对于远程目录的文件列表。 (要点是:您需要将远程目录添加到文件名之前以创建正确限定的路径。) - 您没有处理流事件
error
,所以我怀疑您没有收到有用的错误消息来帮助解决问题。
试试这样的东西:
const Client = require('ssh2').Client;
const conn = new Client();
const sshOpt = someFunctionThatPopulatesSshOptions();
const remoteDir = 'out';
conn.on('ready', () => {
conn.sftp((err, sftp) => {
if (err) throw err;
sftp.readdir(remoteDir, (err, list) => {
if (err) throw err;
let count = list.length;
list.forEach(item => {
let remoteFile = remoteDir + '/' + item.filename;
let localFile = '/tmp/' + item.filename;
console.log('Downloading ' + remoteFile);
sftp.fastGet(remoteFile, localFile, (err) => {
if (err) throw err;
console.log('Downloaded to ' + localFile);
count--;
if (count <= 0) {
conn.end();
}
});
});
});
});
});
conn.on('error', (err) => {
console.error('SSH connection stream problem');
throw err;
});
conn.connect(sshOpt);
这应该可以解决我提到的所有问题。具体来说:
- 我们正在使用
count
变量来确保 SSH 会话仅在所有文件下载完成后关闭。 (我知道它不漂亮。) - 我们正在为所有远程文件下载添加
remoteDir
。 - 我们正在
conn
流中监听error
事件。