SFTP & SCP
SFTPClient
public final class SFTPClient: @unchecked Sendable {
public func listDirectory(_ path: String) async throws -> [SFTPEntry]
public func realpath(_ path: String) async throws -> String
public func stat(_ path: String) async throws -> SFTPAttributes
public func lstat(_ path: String) async throws -> SFTPAttributes
public func setPermissions(_ permissions: UInt32, at path: String) async throws
public func fileSystemAttributes(at path: String) async throws -> [String: UInt64]
public func createDirectory(_ path: String, permissions: UInt32 = 0o755) async throws
public func removeDirectory(_ path: String) async throws
public func removeFile(_ path: String) async throws
public func rename(_ sourcePath: String, to destinationPath: String) async throws
public func readLink(_ path: String) async throws -> String
public func createSymbolicLink(_ linkPath: String, targetPath: String) async throws
public func openFile(
_ path: String,
flags: SFTPFileOpenFlags,
permissions: UInt32 = 0o600
) async throws -> SFTPFileHandle
public func readFile(_ path: String) async throws -> Data
public func writeFile(_ data: Data, to path: String) async throws
public func download(
remotePath: String,
to localURL: URL,
progress: (@Sendable (UInt64, UInt64) -> Void)? = nil
) async throws
public func upload(
localURL: URL,
to remotePath: String,
progress: (@Sendable (UInt64, UInt64) -> Void)? = nil
) async throws
public func resumeDownload(
remotePath: String,
to localURL: URL,
progress: (@Sendable (UInt64, UInt64) -> Void)? = nil
) async throws
public func resumeUpload(
localURL: URL,
to remotePath: String,
progress: (@Sendable (UInt64, UInt64) -> Void)? = nil
) async throws
public func close() async throws
}
Every async method has a callback overload. Progress callbacks deliver (completedBytes, totalBytes) on a dedicated delivery queue targeting the caller’s callbackQueue. resumeDownload resumes from the local file size; resumeUpload resumes from the remote file size.
SFTPFileHandle
public final class SFTPFileHandle: @unchecked Sendable {
public func readData(maximumLength: Int) async throws -> Data
public func writeData(_ data: Data) async throws
public func seek(to offset: UInt64) async throws
public func close() async throws
}
SFTPEntry
public struct SFTPEntry: Equatable, Sendable {
public var filename: String
public var attributes: SFTPAttributes?
public init(filename: String, attributes: SFTPAttributes? = nil)
}
SFTPAttributes
public struct SFTPAttributes: Equatable, Sendable {
public var size: UInt64
public var permissions: UInt32
public var uid: UInt32
public var gid: UInt32
public var type: UInt8
public var accessedAt: Date?
public var modifiedAt: Date?
public init(
size: UInt64,
permissions: UInt32,
uid: UInt32,
gid: UInt32,
type: UInt8,
accessedAt: Date? = nil,
modifiedAt: Date? = nil
)
}
SFTPFileOpenFlags
public struct SFTPFileOpenFlags: OptionSet, Sendable {
public static let read = SFTPFileOpenFlags(rawValue: 1 << 0)
public static let write = SFTPFileOpenFlags(rawValue: 1 << 1)
public static let create = SFTPFileOpenFlags(rawValue: 1 << 2)
public static let truncate = SFTPFileOpenFlags(rawValue: 1 << 3)
public static let append = SFTPFileOpenFlags(rawValue: 1 << 4)
}
SCP extensions
SCP is a public extension SSHConnection — not a separate type. Swift-only; no Obj-C counterpart.
public extension SSHConnection {
func uploadFileWithSCP(
localURL: URL,
toRemotePath remotePath: String,
permissions: UInt16 = 0o644,
maximumSize: UInt64 = 64 * 1024 * 1024
) async throws
func downloadFileWithSCP(
remotePath: String,
toLocalURL localURL: URL,
maximumSize: UInt64 = 64 * 1024 * 1024
) async throws
}
No callback overload; SCP is async-only.