SFTP 客户端 sgcIndy Delphi 组件

· 组件

安全文件传输仍然是企业集成的基石。无论是与银行合作伙伴交换数据、与远程服务器同步文件,还是自动化部署流水线,SFTP(SSH 文件传输协议)都是在不受信任网络上安全传输文件的行业标准。

sgcIndy 包含 TIdSFTPClient——一个原生 Delphi SFTP 客户端组件,通过 SSH 运行,无需外部命令行工具或第三方可执行文件。它通过简洁的事件驱动 API 支持文件上传下载、目录管理、符号链接、文件属性、进度跟踪以及现代加密算法。

本文介绍完整功能集,并提供最常见 SFTP 操作的即用 Delphi 代码。

主要功能

文件传输
以可配置缓冲区大小上传和下载文件,实时进度事件支持。可从文件路径或直接从 TStream 对象传输。
目录操作
列出包含完整元数据的目录,创建和删除目录,解析包括符号链接在内的路径。
现代加密
Curve25519、ECDH、AES-GCM、Ed25519 密钥和 HMAC-SHA2,可配置算法协商以满足合规要求。
多种认证方式
支持密码、公钥(RSA、ECDSA、Ed25519)和键盘交互认证,带指纹回调的主机密钥验证。
文件属性与权限
读取和修改文件权限、所有权、时间戳和大小。完全支持 Unix 风格权限位和符号链接。
进度与事件
以已传输字节数和总大小跟踪传输进度。可取消传输。错误、连接和断开连接事件。

快速入门——连接并下载文件

连接远程服务器、下载文件并断开连接的最简示例。

var
  oSFTP: TIdSFTPClient;
begin
  oSFTP := TIdSFTPClient.Create(nil);
  Try
    oSFTP.Host := 'sftp.example.com';
    oSFTP.Port := 22;
    oSFTP.Authentication.Username := 'deploy';
    oSFTP.Authentication.Password := 'secret';
    oSFTP.Connect;
    // Download a file
    oSFTP.Get('/data/report.csv', 'C:\local\report.csv');
    oSFTP.Disconnect;
  Finally
    oSFTP.Free;
  End;
end;

身份验证

组件支持三种认证方式,默认全部启用——客户端和服务器自动协商最合适的方式。

密码认证

oSFTP.Authentication.Username := 'admin';
oSFTP.Authentication.Password := 'secret';

公钥认证

oSFTP.Authentication.Username := 'deploy';
oSFTP.Authentication.PrivateKeyFile := 'C:\keys\id_rsa';
oSFTP.Authentication.PublicKeyFile := 'C:\keys\id_rsa.pub';
oSFTP.Authentication.Passphrase := 'keypassphrase';

主机密钥验证

通过检查 OnSSHHostKey 事件中的主机密钥指纹来验证服务器身份。

oSFTP.OnSSHHostKey := OnHostKey;
procedure TForm1.OnHostKey(Sender: TObject;
  const aHostKeyType, aFingerprint: string;
  var aAction: TIdSSHHostKeyVerification);
begin
  // Verify fingerprint against known hosts
  if aFingerprint = 'SHA256:xyzABC123...' then
    aAction := sshHostKeyAccept
  else
    aAction := sshHostKeyReject;
end;

文件操作

上传与下载

// Upload a file
oSFTP.Put('C:\local\data.zip', '/uploads/data.zip');
// Download a file
oSFTP.Get('/reports/monthly.pdf', 'C:\local\monthly.pdf');
// Upload from a stream
oSFTP.Put(oMemoryStream, '/uploads/stream-data.bin');
// Download to a stream
oSFTP.Get('/data/export.csv', oFileStream);

字符串便捷方法

// Read a remote file into a string
vContent := oSFTP.GetFileAsString('/config/settings.json');
// Write a string to a remote file
oSFTP.PutFileFromString('{"key":"value"}', '/config/settings.json');

删除、重命名与符号链接

// Delete a remote file
oSFTP.Delete('/tmp/old-file.log');
// Rename / move a file
oSFTP.Rename('/data/temp.csv', '/data/final.csv');
// Create a symbolic link
oSFTP.Symlink('/data/final.csv', '/data/latest.csv');

目录操作

// List directory contents with full metadata
var
  oItems: TIdSFTPDirectoryItems;
  i: Integer;
begin
  oItems := oSFTP.ListDirectory('/data');
  for i := 0 to Length(oItems) - 1 do
    WriteLn(oItems[i].Filename + ' - ' +
      IntToStr(oItems[i].Attrs.Size) + ' bytes');
end;
// Create and remove directories
oSFTP.MakeDirectory('/data/archive/2026');
oSFTP.RemoveDirectory('/data/temp');
// Get current working directory
vPath := oSFTP.GetCurrentDirectory;
// Resolve a path (follows symlinks, resolves . and ..)
vRealPath := oSFTP.RealPath('../data/../data/./file.txt');

文件属性与信息

// Check existence
if oSFTP.FileExists('/data/report.csv') then
  WriteLn('File found');
if oSFTP.DirectoryExists('/data/archive') then
  WriteLn('Directory exists');
// Get file size
vSize := oSFTP.FileSize('/data/report.csv');
// Get full attributes (size, permissions, timestamps, UID/GID)
var
  oAttrs: TIdSFTPFileAttributes;
begin
  oAttrs := oSFTP.Stat('/data/report.csv');
  WriteLn('Size: ' + IntToStr(oAttrs.Size));
  WriteLn('Permissions: ' + IntToStr(oAttrs.Permissions));
end;

传输进度与取消

OnSFTPProgress 事件在每次文件传输过程中触发,提供实时跟踪和中途取消功能。

oSFTP.OnSFTPProgress := OnProgress;
procedure TForm1.OnProgress(Sender: TObject;
  const aFilename: string;
  aTransferred, aTotal: Int64;
  var Cancel: Boolean);
begin
  ProgressBar1.Max := aTotal;
  ProgressBar1.Position := aTransferred;
  Label1.Caption := Format('%s: %d / %d bytes',
    [aFilename, aTransferred, aTotal]);
  // Set Cancel := True to abort the transfer
  Cancel := FUserCancelled;
end;

加密算法配置

组件支持现代加密标准。默认值是安全的,但您可以为合规或互操作性要求自定义算法协商。

类别 支持的算法
密钥交换 Curve25519, ECDH (P-256, P-384, P-521), DH Group14/16
主机密钥 Ed25519, ECDSA (P-256, P-384, P-521), RSA (SHA2-256, SHA2-512)
密码算法 AES-256/192/128-CTR, AES-256/128-GCM
MAC 算法 HMAC-SHA2-256, HMAC-SHA2-512, HMAC-SHA1
// Restrict to only the strongest algorithms
oSFTP.Algorithms.Ciphers := 'aes256-gcm@openssh.com'
		,aes256-ctr';
oSFTP.Algorithms.KexAlgorithms := 'curve25519-sha256';
oSFTP.Algorithms.MACs := 'hmac-sha2-256,hmac-sha2-512';

完整示例

生产就绪示例:使用公钥认证连接、列出目录、带进度跟踪下载文件并处理错误。

uses
  IdSFTPClient, IdSSHClasses;
var
  oSFTP: TIdSFTPClient;
  oItems: TIdSFTPDirectoryItems;
  i: Integer;
begin
  oSFTP := TIdSFTPClient.Create(nil);
  Try
    // Connection
    oSFTP.Host := 'sftp.example.com';
    oSFTP.Port := 22;
    // Public key authentication
    oSFTP.Authentication.Username := 'deploy';
    oSFTP.Authentication.PrivateKeyFile := 'C:\keys\id_ed25519';
    // Events
    oSFTP.OnSFTPProgress := OnProgress;
    oSFTP.OnSFTPError := OnError;
    oSFTP.OnSSHHostKey := OnHostKey;
    // Connect
    oSFTP.Connect;
    // List remote directory
    oItems := oSFTP.ListDirectory('/data');
    for i := 0 to Length(oItems) - 1 do
      WriteLn(oItems[i].Filename);
    // Download file with progress
    oSFTP.Get('/data/backup.tar.gz', 'C:\backups\backup.tar.gz');
    // Disconnect
    oSFTP.Disconnect;
  Finally
    oSFTP.Free;
  End;
end;

方法参考

方法 描述
Get下载文件到本地路径或 TStream
Put从本地路径或 TStream 上传文件
Delete删除远程文件
Rename重命名或移动远程文件
ListDirectory列出包含元数据的目录内容
MakeDirectory创建远程目录
Stat / LStat获取文件属性(含/不含符号链接解析)
FileExists / DirectoryExists检查文件或目录是否存在
Symlink / ReadLink创建或读取符号链接
GetFileAsString / PutFileFromString基于字符串的便捷方法