ftp

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 10 Imported by: 0

README

go-ftp

Thin, testable FTP client built on jlaffaye/ftp.

Install

go get github.com/andywang2011/go-ftp@v0.1.0

Quick start

import (
	"fmt"

	"github.com/andywang2011/go-ftp"
)

cfg := ftp.ConfigDefault()
cfg.Host = "127.0.0.1"
cfg.Port = 65530
cfg.User = "user"
cfg.Password = "secret"

cli, err := ftp.NewClient(cfg)
if err != nil {
	fmt.Println("connect failed")
	return
}
defer cli.Close()
fmt.Println("ok")

Examples

export FTP_HOST=127.0.0.1 FTP_PORT=21 FTP_USER=u FTP_PASSWORD=p
cd go-ftp/examples/basic && go run .
cd go-ftp/examples/resume && go run .

License

MIT — see LICENSE.

Documentation

Overview

Package ftp provides a thin, testable FTP client built on github.com/jlaffaye/ftp.

Design constraints (for use in application frameworks):

  • No viper, no global singletons, no log.Fatal inside the library.
  • Credentials are supplied by the caller; there is no anonymous default user.
  • Use NewClient + Close from main or a dedicated worker; pass context for cancel/timeouts.

Capabilities:

  • Client composes Uploader, Downloader, and Lister (inject narrow interfaces in tests).
  • Streaming transfers with configurable buffer size; optional REST/SIZE resume.
  • ListEach and WalkEach for large directories without holding giant []string slices.

Limitations:

  • Plain FTP only (port 21); FTPS/TLS is not implemented.
  • A single Client supports one data connection at a time; do not run concurrent transfers.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotConnected is returned when an operation runs on a nil or closed client connection.
	ErrNotConnected = errors.New("ftp: not connected")

	// ErrStopIteration may be returned from ListEach/WalkEach callbacks to stop early (not a failure).
	ErrStopIteration = errors.New("ftp: stop iteration")

	// ErrResumeNotSupported indicates the server does not support REST/SIZE or the command failed.
	ErrResumeNotSupported = errors.New("ftp: resume not supported")

	// ErrResumeOffsetMismatch means remote bytes exceed local bytes; remote partial file must be removed.
	ErrResumeOffsetMismatch = errors.New("ftp: resume offset mismatch")

	// ErrResumeNotSeekable means stream resume requires io.Seeker on the reader or writer.
	ErrResumeNotSeekable = errors.New("ftp: resume requires io.Seeker")
)

Functions

This section is empty.

Types

type Client

type Client interface {
	Uploader
	Downloader
	Lister
	Close() error
}

Client is the full FTP capability set (upload, download, list, close). Use narrow interfaces when mocking.

func NewClient

func NewClient(cfg Config) (Client, error)

NewClient dials, logs in, and returns a ready Client. Caller must Close when done.

Example
package main

import (
	"fmt"

	"github.com/andywang2011/go-ftp"
)

func main() {
	cfg := ftp.ConfigDefault()
	cfg.Host = "127.0.0.1"
	cfg.Port = 65530
	cfg.User = "user"
	cfg.Password = "secret"

	cli, err := ftp.NewClient(cfg)
	if err != nil {
		fmt.Println("connect failed")
		return
	}
	defer cli.Close()
	fmt.Println("ok")
}
Output:
connect failed

type Config

type Config struct {
	// Host is the server hostname or IP (required).
	Host string
	// Port is the control port (default 21). FTPS/TLS is not implemented.
	Port int
	// User is the login name (required).
	User string
	// Password is the login password (required).
	Password string
	// Timeout is used for dial and control connection operations (default 30s).
	Timeout time.Duration
	// TransferBufferSize is the default io buffer for uploads/downloads (default 256KiB).
	TransferBufferSize int
}

Config holds FTP connection settings. Credentials must be set by the caller (no anonymous default).

func ConfigDefault

func ConfigDefault() Config

ConfigDefault returns port, timeout, and buffer defaults only. Host, User, and Password must be set by the caller.

func (Config) Addr

func (c Config) Addr() string

Addr returns host:port (call Validate first to apply default port).

func (*Config) Validate

func (c *Config) Validate() error

Validate checks required fields and fills defaults for port, timeout, and buffer size.

type Downloader

type Downloader interface {
	// Download copies remotePath to localPath.
	Download(ctx context.Context, remotePath, localPath string, opts ...TransferOption) error
	// DownloadWriter streams remotePath into w.
	DownloadWriter(ctx context.Context, remotePath string, w io.Writer, opts ...TransferOption) error
}

Downloader downloads remote paths to local paths or io.Writer.

type Entry

type Entry struct {
	// Name is the file or directory name (WalkEach uses the full path).
	Name string
	// Size is the entry size in bytes when known.
	Size uint64
	// Type classifies the entry as file, folder, or link.
	Type EntryType
}

Entry holds metadata for List, ListEach, WalkEach, and ListIter.

type EntryType

type EntryType int

EntryType classifies a remote directory entry.

const (
	EntryTypeFile EntryType = iota
	EntryTypeFolder
	EntryTypeLink
)

type ListIter

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

ListIter iterates directory entries after one LIST (holds a slice internally; prefer ListEach when possible).

func (*ListIter) Next

func (it *ListIter) Next() (Entry, error)

Next returns the next entry or io.EOF when finished.

type Lister

type Lister interface {
	// List returns entry names in remoteDir.
	List(ctx context.Context, remoteDir string) ([]string, error)
	// ListEach invokes fn for each entry without collecting a full slice.
	ListEach(ctx context.Context, remoteDir string, fn func(Entry) error) error
	// ListIter returns a ListIter (same name as type; v0.2 may rename to OpenDirIter).
	ListIter(ctx context.Context, remoteDir string) (*ListIter, error)
	// WalkEach invokes fn for each entry under root recursively.
	WalkEach(ctx context.Context, root string, fn func(Entry) error) error
}

Lister lists and walks remote directories.

type TransferOption

type TransferOption func(*transferOpts)

TransferOption configures a single upload or download.

func WithBufferSize

func WithBufferSize(n int) TransferOption

WithBufferSize sets the copy buffer for one transfer (overrides Config.TransferBufferSize).

func WithResume

func WithResume(enabled bool) TransferOption

WithResume enables automatic offset detection for path-based transfers (requires REST/SIZE).

func WithResumeOffset

func WithResumeOffset(n int64) TransferOption

WithResumeOffset sets an explicit start byte; streaming transfers require io.Seeker.

type Uploader

type Uploader interface {
	// Upload copies localPath to remotePath.
	Upload(ctx context.Context, localPath, remotePath string, opts ...TransferOption) error
	// UploadReader copies r to remotePath.
	UploadReader(ctx context.Context, r io.Reader, remotePath string, opts ...TransferOption) error
}

Uploader uploads local paths or io.Reader to remote paths.

Jump to

Keyboard shortcuts

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