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

Node.js中使用ssh2-sftp-client下载SFTP全量文件及FTP实现咨询

SFTP 递归下载完整实现方案

现有代码问题

  • await data.forEach() 写法无效,forEach 没有返回 Promise,无法等待所有下载任务完成,容易出现连接提前断开、文件下载不全的问题
  • 未判断远程条目类型,直接调用 sftp.get() 遇到文件夹会直接报错
  • 没有处理嵌套子目录,也没有提前创建本地对应层级的目录结构

修复后可递归下载所有文件/文件夹的代码

const fs = require('fs/promises')
const Client = require('ssh2-sftp-client')
const sftp = new Client()

checkCtrl.checkSftp = async (req, res) => {
  const { url: host, username, password, port, remotePath = '/', localPath = './ftp' } = req.body
  // 递归下载函数封装
  const downloadDir = async (remoteDir, localDir) => {
    // 递归创建本地目录,不存在自动生成父级目录
    await fs.mkdir(localDir, { recursive: true })
    // 获取远程目录下所有条目
    const entries = await sftp.list(remoteDir)
    // 并行处理所有条目,等待全部任务完成
    await Promise.all(entries.map(async entry => {
      const curRemotePath = `${remoteDir}/${entry.name}`.replace(/\/+/g, '/')
      const curLocalPath = `${localDir}/${entry.name}`
      // 类型为d代表目录,递归调用下载
      if (entry.type === 'd') {
        await downloadDir(curRemotePath, curLocalPath)
      // 类型为-代表普通文件,直接下载
      } else if (entry.type === '-') {
        const fileStream = await sftp.get(curRemotePath)
        await fs.writeFile(curLocalPath, fileStream)
      }
    }))
  }

  try {
    // 建立连接
    await sftp.connect({
      host,
      port,
      username,
      password,
      keepaliveInterval: 2000,
      keepaliveCountMax: 20
    })
    // 启动递归下载
    await downloadDir(remotePath, localPath)
    // 下载完成关闭连接
    await sftp.end()
    res.status(200).send('下载成功')
  } catch (err) {
    console.log('下载出错', err)
    await sftp.end().catch(() => {})
    res.status(400).send('下载失败')
  }
}

代码支持自定义远程下载路径和本地存储路径,自动处理多层嵌套目录,所有异步任务执行完成后才会返回响应。

FTP 服务器同款功能实现建议
  • 推荐使用 basic-ftp 包实现 FTP 连接操作,逻辑和 SFTP 实现完全一致
    1. 建立 FTP 连接后调用 list() 方法获取指定目录下的所有条目
    2. 同样通过条目类型判断是目录还是普通文件,目录递归处理,文件调用 downloadTo() 方法直接下载到本地路径
    3. 下载前用 fs.mkdir({recursive: true}) 提前创建本地对应目录结构
  • 注意配置 FTP 连接的被动模式,大部分公网 FTP 服务器都要求使用被动模式连接
  • 下载完成后手动调用 close() 方法关闭 FTP 连接,避免连接资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:51:03