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

如何提升Windows PowerShell下SFTP文件拉取的性能?

PowerShell SFTP批量下载脚本优化方案

问题分析

你当前的脚本通过Transferetto模块串行下载220个10-14KB的小文件耗时近15分钟,核心瓶颈在于串行处理带来的重复连接开销——每个小文件传输都要经历单独的会话握手、等待确认,叠加起来拖慢了整体效率。

具体优化方法

1. 启用并行下载(最显著提升效率)

串行下载的握手等待是最大耗时点,改用并行处理可以把总耗时压缩到数分钟内。根据你的PowerShell版本选择方案:

方案1:PowerShell 7+ 用ForEach-Object -Parallel

Set-ExecutionPolicy RemoteSigned -Scope Process -Force
Import-Module Transferetto

# 配置基础参数
$server = '124.77.98.211'
$username = 'FTDD'
$password = 'RRGGTIjhh78'
$localBasePath = "\\data\file\"

# 先获取文件列表
$sftpConn = Connect-SFTP -Server $server -Username $username -Password $password
$fileList = Get-SFTPList -SftpClient $sftpConn -Path '/FTDD'
Disconnect-SFTP -SftpClient $sftpConn

# 并行下载,控制并发数避免服务器过载
$fileList | ForEach-Object -Parallel {
    Import-Module Transferetto
    $conn = Connect-SFTP -Server $using:server -Username $using:username -Password $using:password
    Receive-SFTPFile -SftpClient $conn -RemotePath $_.FullName -LocalPath "$using:localBasePath$($_.Name)"
    Write-Host "完成下载:$($_.FullName)"
    Disconnect-SFTP -SftpClient $conn
} -ThrottleLimit 10  # 并发数可根据网络和服务器负载调整,建议5-15之间

方案2:PowerShell 5.x 用Start-Job

Set-ExecutionPolicy RemoteSigned -Scope Process -Force
Import-Module Transferetto

# 配置基础参数
$server = '124.77.98.211'
$username = 'FTDD'
$password = 'RRGGTIjhh78'
$localBasePath = "\\data\file\"

# 先获取文件列表
$sftpConn = Connect-SFTP -Server $server -Username $username -Password $password
$fileList = Get-SFTPList -SftpClient $sftpConn -Path '/FTDD'
Disconnect-SFTP -SftpClient $sftpConn

# 创建批量下载任务
$downloadJobs = $fileList | ForEach-Object {
    Start-Job -ScriptBlock {
        param($file, $server, $user, $pwd, $localPath)
        Import-Module Transferetto
        $conn = Connect-SFTP -Server $server -Username $user -Password $pwd
        Receive-SFTPFile -SftpClient $conn -RemotePath $file.FullName -LocalPath "$localPath$($file.Name)"
        Write-Host "完成下载:$($file.FullName)"
        Disconnect-SFTP -SftpClient $conn
    } -ArgumentList $_, $server, $username, $password, $localBasePath
}

# 等待所有任务完成并清理
Wait-Job $downloadJobs | Out-Null
Receive-Job $downloadJobs | Out-Null
Remove-Job $downloadJobs

2. 调整Transferetto传输参数

  • 增大缓冲区:给Receive-SFTPFile添加-BufferSize参数,减少IO交互次数,比如设置为64KB:
    Receive-SFTPFile -SftpClient $SftpClient -RemotePath $File.FullName -LocalPath "\\data\file\$($File.Name)" -BufferSize 65536
    
  • 启用传输压缩:连接SFTP时开启压缩,减少小文件的传输字节数:
    $SftpClient = Connect-SFTP -Server '124.77.98.211' -Username 'FTDD' -Password 'RRGGTIjhh78' -Compression $true
    

3. 跳过已存在的文件

下载前检查本地文件是否存在且大小一致,避免重复下载浪费时间:

foreach ($File in $List) {
    $localFilePath = "\\data\file\$($File.Name)"
    if (-not (Test-Path $localFilePath) -or (Get-Item $localFilePath).Length -ne $File.Length) {
        Receive-SFTPFile -SftpClient $SftpClient -RemotePath $File.FullName -LocalPath $localFilePath
        Write-Host "已下载:$($File.FullName)"
    } else {
        Write-Host "跳过已存在文件:$($File.Name)"
    }
}

4. 更换更高效的SFTP模块

Transferetto基于SSH.NET封装,部分场景下原生使用WinSCP模块(支持多线程批量下载)效率更高:

Set-ExecutionPolicy RemoteSigned -Scope Process -Force
# 先安装WinSCP模块:Install-Module -Name WinSCP

$sessionOpts = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Sftp
    HostName = '124.77.98.211'
    UserName = 'FTDD'
    Password = 'RRGGTIjhh78'
}

$session = New-Object WinSCP.Session
$session.Open($sessionOpts)

# WinSCP默认多线程批量下载,直接拉取目录下所有文件
$session.GetFiles('/FTDD/*', '\\data\file\*').Check()

$session.Dispose()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:02:34