You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js从SFTP下载.txt.pgp文件失败的技术求助

SFTP下载.txt.pgp文件失败的排查与解决

兄弟,我之前踩过几乎一模一样的SFTP下载坑——能拿到文件列表但死活下不了文件,结合你用的几个npm包,给你捋捋问题所在和解决办法:

先排查最容易忽略的核心问题

  • 本地权限与路径:先确认本地目标文件夹有没有写入权限(比如你用root跑Node但目标文件夹是普通用户权限,或者反过来);另外一定要用绝对路径保存文件,相对路径很容易写到你没注意的地方(比如项目根目录之外)。
  • 远程路径正确性:你用readdir/list拿到的可能是相对路径,下载时一定要拼上远程服务器的根目录(比如远程文件夹是/data/files,不能只写test.txt.pgp,要写/data/files/test.txt.pgp)。

针对你用的几个包的正确实现

1. ssh2 包的正确fastGet写法

很多人栽在异步操作未完成就关闭连接上,给你补全完整可运行的代码:

const Client = require('ssh2').Client;
const fs = require('fs');
const path = require('path');

const conn = new Client();
conn.on('ready', () => {
  console.log('Client :: ready');
  conn.sftp((err, sftp) => {
    if (err) throw err;
    // 务必用远程绝对路径
    const remoteFilePath = '/remote/server/path/your-file.txt.pgp';
    // 用path.resolve生成本地绝对路径,确保文件夹存在
    const localFilePath = path.resolve(__dirname, './downloads/your-file.txt.pgp');
    fs.mkdirSync(path.dirname(localFilePath), { recursive: true });

    // fastGet的回调里再关闭连接,确保下载完成
    sftp.fastGet(remoteFilePath, localFilePath, (err) => {
      if (err) {
        console.error('下载失败:', err.message);
      } else {
        console.log('文件成功保存到:', localFilePath);
      }
      conn.end(); // 必须等下载完成再关连接
    });
  });
}).connect({
  host: '你的SFTP服务器地址',
  port: 22,
  username: '你的用户名',
  password: '你的密码' // 或者用privateKey: fs.readFileSync('./your-key.pem')
});

重点提示:如果提前调用conn.end(),进程会直接终止,下载操作还没完成就被打断,本地自然没有文件。

2. ssh2-sftp-client 包的正确写法

这个包用Promise封装更友好,一定要用await等待异步操作完成:

const SftpClient = require('ssh2-sftp-client');
const path = require('path');

async function downloadPGPFile() {
  const sftp = new SftpClient();
  try {
    await sftp.connect({
      host: '你的SFTP服务器地址',
      port: 22,
      username: '你的用户名',
      password: '你的密码'
    });
    console.log('SFTP连接成功');
    
    const remotePath = '/remote/server/path/your-file.txt.pgp';
    const localPath = path.resolve(__dirname, './downloads/your-file.txt.pgp');
    // 先创建本地文件夹(如果不存在)
    await sftp.mkdir(path.dirname(localPath), { recursive: true });
    
    // 用get方法或者fastGet都可以
    await sftp.get(remotePath, localPath);
    console.log('下载完成,文件路径:', localPath);
  } catch (err) {
    console.error('下载出错:', err.message);
  } finally {
    // 无论成功失败都要关闭连接
    await sftp.end();
  }
}

// 调用异步函数
downloadPGPFile();

坑点:如果不用await,函数会直接执行完毕,进程退出,下载操作根本没机会执行。

3. node-ssh 包的实现

node-ssh的SFTP下载同样要注意异步等待:

const NodeSSH = require('node-ssh');
const path = require('path');

const ssh = new NodeSSH();

async function fetchPGPFile() {
  try {
    await ssh.connect({
      host: '你的SFTP服务器地址',
      username: '你的用户名',
      password: '你的密码'
    });
    const remotePath = '/remote/server/path/your-file.txt.pgp';
    const localPath = path.resolve(__dirname, './downloads/your-file.txt.pgp');
    // 用sftpFastGet提升下载速度
    await ssh.sftpFastGet(remotePath, localPath);
    console.log('文件下载成功');
  } catch (err) {
    console.error('操作失败:', err.message);
  } finally {
    ssh.dispose(); // 释放连接
  }
}

fetchPGPFile();

额外排查技巧

  • 开启debug日志:在连接配置里加debug: console.log,能看到SFTP的交互细节,比如服务器是否返回错误、文件是否存在:
    // 以ssh2为例
    conn.connect({
      // 其他配置
      debug: (msg) => console.log('SFTP Debug:', msg)
    });
    
  • 检查文件状态:用sftp.stat(remotePath)获取远程文件的大小、权限等信息,下载后对比本地文件大小,如果本地是0字节,大概率是连接提前关闭或者权限问题。

内容的提问来源于stack exchange,提问作者Viet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:12:41