sshtransfer

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 20, 2025 License: MIT Imports: 10 Imported by: 0

README

sshtransfer

Go Reference Go Report Card CI

Efficient file transfer over SSH for Go. Download and upload files in batches through a single SSH tunnel with automatic retry logic.

Features

  • 🚀 Batch transfers - multiple files through one SSH connection
  • 🔄 Auto-retry - automatic reconnection on network failures
  • 🗜️ Compression - on-the-fly data compression
  • 📊 Progress tracking - real-time transfer statistics
  • 🔀 Two modes - rsync (resumable) or tar (faster for small files)
  • 🔐 Secure - uses your existing SSH keys
  • Connection reuse - SSH ControlMaster for efficiency

Installation

go get github.com/AslanKarimov46/sshtransfer

Quick Start

package main

import (
    "context"
    "log"
    
    "github.com/AslanKarimov46/sshtransfer"
)

func main() {
    client := sshtransfer.New("user@server.com",
        sshtransfer.WithRemoteBase("/data/files/"),
        sshtransfer.WithLocalBase("./downloads/"),
    )
    defer client.Close()

    ctx := context.Background()

    // Check connection
    if err := client.Ping(ctx); err != nil {
        log.Fatal("Cannot connect:", err)
    }

    // Download single file
    if err := client.Download(ctx, "document.pdf"); err != nil {
        log.Fatal(err)
    }
    
    log.Println("Downloaded successfully!")
}

Batch Transfer

Transfer multiple files efficiently through a single SSH connection:

files := []string{
    "recordings/2024-01-01/audio1.mp3",
    "recordings/2024-01-01/audio2.mp3",
    "recordings/2024-01-02/audio3.mp3",
}

result, err := client.DownloadBatch(ctx, files)
if err != nil {
    log.Fatal(err)
}

log.Printf("✓ Downloaded %d files in %v", result.Success, result.Duration)

Auto-Retry

Configure automatic retry on connection failures:

client := sshtransfer.New("user@server.com",
    sshtransfer.WithRetryAttempts(5),     // retry up to 5 times
    sshtransfer.WithRetryDelay(3*time.Second), // wait 3s between retries
)

Progress Tracking

result, err := client.DownloadBatch(ctx, files,
    sshtransfer.WithProgress(func(p sshtransfer.Progress) {
        fmt.Printf("\r[%3.0f%%] %d/%d files | %s | %s | ETA: %v",
            p.Percent(),
            p.FilesDone,
            p.FilesTotal,
            p.BytesHuman(),
            p.SpeedHuman(),
            p.ETA(),
        )
    }),
)

Upload Files

// Single file
err := client.Upload(ctx, "local/report.pdf", "remote/reports/report.pdf")

// Batch upload
result, err := client.UploadBatch(ctx, []string{
    "file1.txt",
    "file2.txt",
})

Delete Remote Files

// Delete single file
err := client.Delete(ctx, "old-file.txt")

// Delete multiple files
err := client.DeleteBatch(ctx, []string{"file1.txt", "file2.txt"})

Transfer Modes

// rsync mode (default) - supports resume, good for large files
client := sshtransfer.New(host, sshtransfer.WithMode(sshtransfer.ModeRsync))

// tar mode - faster for many small files
client := sshtransfer.New(host, sshtransfer.WithMode(sshtransfer.ModeTar))

API Reference

Client Methods
Method Description
New(host, ...options) Create new client
Close() Close connection
Ping(ctx) Check connection
Download(ctx, path) Download single file
Upload(ctx, local, remote) Upload single file
DownloadBatch(ctx, paths) Download multiple files
UploadBatch(ctx, paths) Upload multiple files
Delete(ctx, path) Delete remote file
DeleteBatch(ctx, paths) Delete multiple remote files
Exists(ctx, path) Check if file exists
Size(ctx, path) Get file size
List(ctx, dir) List directory contents
Configuration Options
Option Description Default
WithRemoteBase(path) Base path on remote server /
WithLocalBase(path) Local base path .
WithKeyFile(path) SSH private key ~/.ssh/id_rsa
WithPort(port) SSH port 22
WithMode(mode) Transfer mode: ModeRsync / ModeTar ModeRsync
WithCompress(bool) Enable compression true
WithTimeout(duration) Connection timeout 30s
WithRetryAttempts(n) Number of retry attempts 3
WithRetryDelay(duration) Delay between retries 3s
WithProgress(fn) Progress callback nil
WithControlMaster(bool) Reuse SSH connections true

Requirements

  • Go 1.21+
  • rsync installed on both local and remote (for ModeRsync)
  • tar installed on both sides (for ModeTar)
  • SSH key-based authentication configured

Performance

Comparison for transferring 100 files (50MB total) over 1Gbit network:

Method Time SSH Connections
Individual SCP ~45s 100
SSHFS + copy ~30s 1 (FUSE overhead)
sshtransfer batch ~12s 1

Examples

See the examples directory:

Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.

License

MIT License - see LICENSE for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrConnectionFailed is returned when SSH connection fails.
	ErrConnectionFailed = errors.New("ssh connection failed")

	// ErrAuthFailed is returned when authentication fails.
	ErrAuthFailed = errors.New("ssh authentication failed")

	// ErrFileNotFound is returned when a remote file doesn't exist.
	ErrFileNotFound = errors.New("file not found")

	// ErrPermissionDenied is returned when permission is denied.
	ErrPermissionDenied = errors.New("permission denied")

	// ErrTimeout is returned when an operation times out.
	ErrTimeout = errors.New("operation timed out")

	// ErrNoFiles is returned when no files are provided for batch operation.
	ErrNoFiles = errors.New("no files provided")

	// ErrRsyncNotFound is returned when rsync is not installed.
	ErrRsyncNotFound = errors.New("rsync not found on system")

	// ErrTarNotFound is returned when tar is not installed.
	ErrTarNotFound = errors.New("tar not found on system")
)

Common errors returned by the package.

Functions

This section is empty.

Types

type BatchError

type BatchError struct {
	// Errors is a map of file paths to their errors.
	Errors map[string]error
}

BatchError contains errors from a batch operation.

func (*BatchError) Error

func (e *BatchError) Error() string

Error returns the error message.

func (*BatchError) HasErrors

func (e *BatchError) HasErrors() bool

HasErrors returns true if there are any errors.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an SSH file transfer client.

func New

func New(host string, options ...Option) *Client

New creates a new SSH transfer client.

The host should be in the format "user@hostname" or just "hostname".

func (*Client) Close

func (c *Client) Close() error

Close closes the SSH connection. If ControlMaster is enabled, this terminates the master connection.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, remotePath string) error

Delete deletes a file on the remote server.

func (*Client) DeleteBatch

func (c *Client) DeleteBatch(ctx context.Context, remotePaths []string) error

DeleteBatch deletes multiple files on the remote server.

func (*Client) Download

func (c *Client) Download(ctx context.Context, remotePath string) error

Download downloads a single file from the remote server.

func (*Client) DownloadBatch

func (c *Client) DownloadBatch(ctx context.Context, remotePaths []string, options ...Option) (*Result, error)

DownloadBatch downloads multiple files through a single SSH connection. This is more efficient than calling Download multiple times.

func (*Client) Exists

func (c *Client) Exists(ctx context.Context, remotePath string) bool

Exists checks if a file exists on the remote server.

func (*Client) Host

func (c *Client) Host() string

Host returns the remote host.

func (*Client) List

func (c *Client) List(ctx context.Context, remotePath string) ([]string, error)

List returns a list of files in a remote directory.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping checks if the remote host is reachable. It attempts to connect and will retry according to the retry settings.

func (*Client) Size

func (c *Client) Size(ctx context.Context, remotePath string) (int64, error)

Size returns the size of a file on the remote server.

func (*Client) Upload

func (c *Client) Upload(ctx context.Context, localPath, remotePath string) error

Upload uploads a single file to the remote server.

func (*Client) UploadBatch

func (c *Client) UploadBatch(ctx context.Context, localPaths []string, options ...Option) (*Result, error)

UploadBatch uploads multiple files through a single SSH connection.

type Mode

type Mode int

Mode represents the transfer mode.

const (
	// ModeRsync uses rsync for file transfers.
	// Supports resuming interrupted transfers and delta-transfer.
	// Best for large files.
	ModeRsync Mode = iota

	// ModeTar uses tar over SSH pipe.
	// Faster for many small files but doesn't support resume.
	ModeTar
)

func (Mode) String

func (m Mode) String() string

String returns the string representation of the mode.

type Option

type Option func(*Options)

Option is a function that modifies Options.

func WithCompress

func WithCompress(compress bool) Option

WithCompress enables or disables compression.

func WithControlMaster

func WithControlMaster(enable bool) Option

WithControlMaster enables or disables SSH connection reuse.

func WithControlPersist

func WithControlPersist(duration time.Duration) Option

WithControlPersist sets how long to keep the master connection alive.

func WithKeyFile

func WithKeyFile(path string) Option

WithKeyFile sets the path to the SSH private key.

func WithLocalBase

func WithLocalBase(path string) Option

WithLocalBase sets the local base path.

func WithMode

func WithMode(mode Mode) Option

WithMode sets the transfer mode.

func WithPort

func WithPort(port int) Option

WithPort sets the SSH port.

func WithProgress

func WithProgress(fn func(Progress)) Option

WithProgress sets the progress callback function.

func WithRemoteBase

func WithRemoteBase(path string) Option

WithRemoteBase sets the base path on the remote server.

func WithRetryAttempts

func WithRetryAttempts(attempts int) Option

WithRetryAttempts sets the number of retry attempts.

func WithRetryDelay

func WithRetryDelay(delay time.Duration) Option

WithRetryDelay sets the delay between retry attempts.

func WithStrictHostKey

func WithStrictHostKey(strict bool) Option

WithStrictHostKey enables or disables strict host key checking.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the connection timeout.

type Options

type Options struct {
	// RemoteBase is the base path on the remote server.
	// All remote paths will be relative to this.
	RemoteBase string

	// LocalBase is the base path on the local system.
	// All local paths will be relative to this.
	LocalBase string

	// KeyFile is the path to the SSH private key.
	// Supports ~ for home directory.
	KeyFile string

	// Port is the SSH port.
	Port int

	// Mode is the transfer mode (rsync or tar).
	Mode Mode

	// Compress enables data compression during transfer.
	Compress bool

	// Timeout is the SSH connection timeout.
	Timeout time.Duration

	// RetryAttempts is the number of retry attempts on failure.
	RetryAttempts int

	// RetryDelay is the delay between retry attempts.
	RetryDelay time.Duration

	// ControlMaster enables SSH connection reuse.
	ControlMaster bool

	// ControlPersist is how long to keep the master connection alive.
	ControlPersist time.Duration

	// StrictHostKey enables strict host key checking.
	StrictHostKey bool

	// ProgressFn is called with progress updates during transfers.
	ProgressFn func(Progress)
}

Options holds the client configuration.

func DefaultOptions

func DefaultOptions() *Options

DefaultOptions returns the default configuration.

type Progress

type Progress struct {
	// FilesTotal is the total number of files to transfer.
	FilesTotal int

	// FilesDone is the number of files completed.
	FilesDone int

	// BytesTotal is the total number of bytes to transfer (if known).
	BytesTotal int64

	// BytesDone is the number of bytes transferred.
	BytesDone int64

	// CurrentFile is the name of the file currently being transferred.
	CurrentFile string

	// StartTime is when the transfer started.
	StartTime time.Time

	// LastUpdate is when progress was last updated.
	LastUpdate time.Time
}

Progress holds information about transfer progress.

func (Progress) BytesHuman

func (p Progress) BytesHuman() string

BytesHuman returns the bytes transferred in human-readable format.

func (Progress) ETA

func (p Progress) ETA() time.Duration

ETA returns the estimated time remaining.

func (Progress) Elapsed

func (p Progress) Elapsed() time.Duration

Elapsed returns the time elapsed since the transfer started.

func (Progress) Percent

func (p Progress) Percent() float64

Percent returns the completion percentage (0-100).

func (Progress) Speed

func (p Progress) Speed() float64

Speed returns the transfer speed in bytes per second.

func (Progress) SpeedHuman

func (p Progress) SpeedHuman() string

SpeedHuman returns the transfer speed in human-readable format.

func (Progress) TotalHuman

func (p Progress) TotalHuman() string

TotalHuman returns the total bytes in human-readable format.

type Result

type Result struct {
	// Success is the number of successfully transferred files.
	Success int

	// Failed is the number of failed transfers.
	Failed int

	// Bytes is the total bytes transferred.
	Bytes int64

	// Duration is how long the transfer took.
	Duration time.Duration

	// Errors contains any errors that occurred.
	Errors []error
}

Result holds the result of a transfer operation.

type RetryError

type RetryError struct {
	// Attempts is the number of attempts made.
	Attempts int

	// LastErr is the last error encountered.
	LastErr error
}

RetryError is returned when all retry attempts fail.

func (*RetryError) Error

func (e *RetryError) Error() string

Error returns the error message.

func (*RetryError) Unwrap

func (e *RetryError) Unwrap() error

Unwrap returns the underlying error.

type TransferError

type TransferError struct {
	// Op is the operation that failed (download, upload, delete).
	Op string

	// Path is the file path that caused the error.
	Path string

	// Host is the remote host.
	Host string

	// Err is the underlying error.
	Err error
}

TransferError represents an error during file transfer.

func (*TransferError) Error

func (e *TransferError) Error() string

Error returns the error message.

func (*TransferError) Unwrap

func (e *TransferError) Unwrap() error

Unwrap returns the underlying error.

Directories

Path Synopsis
examples
basic command
Example: Basic file download and upload operations
Example: Basic file download and upload operations
batch command
Example: Batch file transfer operations
Example: Batch file transfer operations
progress command
Example: Download with progress tracking
Example: Download with progress tracking

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL