Documentation ¶
Overview ¶
Package goftp provides a high-level FTP client for go.
Example ¶
package main import ( "os" "github.com/secsy/goftp" ) func main() { // Create client object with default config client, err := goftp.Dial("ftp.example.com") if err != nil { panic(err) } // Download a file to disk readme, err := os.Create("readme") if err != nil { panic(err) } err = client.Retrieve("README", readme) if err != nil { panic(err) } // Upload a file from disk bigFile, err := os.Open("big_file") if err != nil { panic(err) } err = client.Store("big_file", bigFile) if err != nil { panic(err) } }
Output:
Example (Config) ¶
package main import ( "bytes" "os" "time" "github.com/secsy/goftp" ) func main() { config := goftp.Config{ User: "jlpicard", Password: "beverly123", ConnectionsPerHost: 10, Timeout: 10 * time.Second, Logger: os.Stderr, } client, err := goftp.DialConfig(config, "ftp.example.com") if err != nil { panic(err) } // download to a buffer instead of file buf := new(bytes.Buffer) err = client.Retrieve("pub/interesting_file.txt", buf) if err != nil { panic(err) } }
Output:
Index ¶
- type Client
- func (c *Client) Close() error
- func (c *Client) Delete(path string) error
- func (c *Client) Getwd() (string, error)
- func (c *Client) Mkdir(path string) (string, error)
- func (c *Client) OpenRawConn() (RawConn, error)
- func (c *Client) ReadDir(path string) ([]os.FileInfo, error)
- func (c *Client) Rename(from, to string) error
- func (c *Client) Retrieve(path string, dest io.Writer) error
- func (c *Client) Rmdir(path string) error
- func (c *Client) Stat(path string) (os.FileInfo, error)
- func (c *Client) Store(path string, src io.Reader) error
- type Config
- type Error
- type RawConn
- type TLSMode
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client maintains a connection pool to the FTP server(s), so you typically only need one Client object. Client methods are safe to call concurrently from different goroutines, but once you are using all ConnectionsPerHost connections per host, methods will block waiting for a free connection.
func Dial ¶
Dial creates an FTP client using the default config. See DialConfig for information about "hosts".
func DialConfig ¶
DialConfig creates an FTP client using the given config. "hosts" is a list of IP addresses or hostnames with an optional port (defaults to 21). Hostnames will be expanded to all the IP addresses they resolve to. The client's connection pool will pick from all the addresses in a round-robin fashion. If you specify multiple hosts, they should be identical mirrors of each other.
func (*Client) Close ¶
Close closes all open server connections. Currently this does not attempt to do any kind of polite FTP connection termination. It will interrupt all transfers in progress.
func (*Client) Mkdir ¶
Mkdir creates directory "path". The returned string is how the client should refer to the created directory.
func (*Client) OpenRawConn ¶
OpenRawConn opens a "raw" connection to the server which allows you to run any control or data command you want. See the RawConn interface for more details. The RawConn will not participate in the Client's pool (i.e. does not count against ConnectionsPerHost).
Example ¶
package main import ( "fmt" "io/ioutil" "github.com/secsy/goftp" ) func main() { // ignore errors for brevity client, _ := goftp.Dial("ftp.hq.nasa.gov") rawConn, _ := client.OpenRawConn() code, msg, _ := rawConn.SendCommand("FEAT") fmt.Printf("FEAT: %d-%s\n", code, msg) // prepare data connection dcGetter, _ := rawConn.PrepareDataConn() // cause server to initiate data connection rawConn.SendCommand("LIST") // get actual data connection dc, _ := dcGetter() data, _ := ioutil.ReadAll(dc) fmt.Printf("LIST response: %s\n", data) // close data connection dc.Close() // read final response from server after data transfer code, msg, _ = rawConn.ReadResponse() fmt.Printf("Final response: %d-%s\n", code, msg) }
Output:
func (*Client) ReadDir ¶
ReadDir fetches the contents of a directory, returning a list of os.FileInfo's which are relatively easy to work with programatically. It will not return entries corresponding to the current directory or parent directories. The os.FileInfo's fields may be incomplete depending on what the server supports. If the server does not support "MLSD", "LIST" will be used. You may have to set ServerLocation in your config to get (more) accurate ModTimes in this case.
Example (ParallelWalk) ¶
Just for fun, walk an ftp server in parallel. I make no claim that this is correct or a good idea.
package main import ( "fmt" "os" "path" "path/filepath" "sync/atomic" "github.com/secsy/goftp" ) // Just for fun, walk an ftp server in parallel. I make no claim that this is // correct or a good idea. func main() { client, err := goftp.Dial("ftp.hq.nasa.gov") if err != nil { panic(err) } Walk(client, "", func(fullPath string, info os.FileInfo, err error) error { if err != nil { // no permissions is okay, keep walking if err.(goftp.Error).Code() == 550 { return nil } return err } fmt.Println(fullPath) return nil }) } // Walk a FTP file tree in parallel with prunability and error handling. // See http://golang.org/pkg/path/filepath/#Walk for interface details. func Walk(client *goftp.Client, root string, walkFn filepath.WalkFunc) (ret error) { dirsToCheck := make(chan string, 100) var workCount int32 = 1 dirsToCheck <- root for dir := range dirsToCheck { go func(dir string) { files, err := client.ReadDir(dir) if err != nil { if err = walkFn(dir, nil, err); err != nil && err != filepath.SkipDir { ret = err close(dirsToCheck) return } } for _, file := range files { if err = walkFn(path.Join(dir, file.Name()), file, nil); err != nil { if file.IsDir() && err == filepath.SkipDir { continue } ret = err close(dirsToCheck) return } if file.IsDir() { atomic.AddInt32(&workCount, 1) dirsToCheck <- path.Join(dir, file.Name()) } } atomic.AddInt32(&workCount, -1) if workCount == 0 { close(dirsToCheck) } }(dir) } return ret }
Output:
func (*Client) Retrieve ¶
Retrieve file "path" from server and write bytes to "dest". If the server supports resuming stream transfers, Retrieve will continue resuming a failed download as long as it continues making progress. Retrieve will also verify the file's size after the transfer if the server supports the SIZE command.
func (*Client) Stat ¶
Stat fetches details for a particular file. The os.FileInfo's fields may be incomplete depending on what the server supports. If the server doesn't support "MLST", "LIST" will be attempted, but "LIST" will not work if path is a directory. You may have to set ServerLocation in your config to get (more) accurate ModTimes when using "LIST".
func (*Client) Store ¶
Store bytes read from "src" into file "path" on the server. If the server supports resuming stream transfers and "src" is an io.Seeker (*os.File is an io.Seeker), Store will continue resuming a failed upload as long as it continues making progress. Store will not attempt to resume an upload if the client is connected to multiple servers. Store will also verify the remote file's size after the transfer if the server supports the SIZE command.
type Config ¶
type Config struct { // User name. Defaults to "anonymous". User string // User password. Defaults to "anonymous" if required. Password string // Maximum number of FTP connections to open per-host. Defaults to 5. Keep in // mind that FTP servers typically limit how many connections a single user // may have open at once, so you may need to lower this if you are doing // concurrent transfers. ConnectionsPerHost int // Timeout for opening connections, sending control commands, and each read/write // of data transfers. Defaults to 5 seconds. Timeout time.Duration // TLS Config used for FTPS. If provided, it will be an error if the server // does not support TLS. Both the control and data connection will use TLS. TLSConfig *tls.Config // FTPS mode. TLSExplicit means connect non-TLS, then upgrade connection to // TLS via "AUTH TLS" command. TLSImplicit means open the connection using // TLS. Defaults to TLSExplicit. TLSMode TLSMode // This flag controls whether to use IPv6 addresses found when resolving // hostnames. Defaults to false to prevent failures when your computer can't // IPv6. If the hostname(s) only resolve to IPv6 addresses, Dial() will still // try to use them as a last ditch effort. You can still directly give an // IPv6 address to Dial() even with this flag off. IPv6Lookup bool // Logging destination for debugging messages. Set to os.Stderr to log to stderr. // Password value will not be logged. Logger io.Writer // Time zone of the FTP server. Used when parsing mtime from "LIST" output if // server does not support "MLST"/"MLSD". Defaults to UTC. ServerLocation *time.Location // Enable "active" FTP data connections where the server connects to the client to // establish data connections (does not work if client is behind NAT). If TLSConfig // is specified, it will be used when listening for active connections. ActiveTransfers bool // Set the host:port to listen on for active data connections. If the host and/or // port is empty, the local address/port of the control connection will be used. A // port of 0 will listen on a random port. If not specified, the default behavior is // ":0", i.e. listen on the local control connection host and a random port. ActiveListenAddr string // Disables EPSV in favour of PASV. This is useful in cases where EPSV connections // neither complete nor downgrade to PASV successfully by themselves, resulting in // hung connections. DisableEPSV bool // contains filtered or unexported fields }
Config contains configuration for a Client object.
type Error ¶
type Error interface { error // Whether the error was transient and attempting the same operation // again may be succesful. This includes timeouts. Temporary() bool // If the error originated from an unexpected response from the server, this // will return the FTP response code. Otherwise it will return 0. Code() int // Similarly, this will return the text response from the server, or empty // string. Message() string }
Error is an expanded error interface returned by all Client methods. It allows discerning callers to discover potentially actionable qualities of the error.
type RawConn ¶
type RawConn interface { // Sends command fmt.Sprintf(f, args...) to the server, returning the response code, // response message, and error if any. SendCommand(f string, args ...interface{}) (int, string, error) // Prepares a data connection to the server. PrepareDataConn returns a getter function // because in active transfer mode you must first call PrepareDataConn (to tell server // what port to connect to), then send a control command to tell the server to initiate // a connection, then finally you invoke the getter function to get the actual // net.Conn. PrepareDataConn() (func() (net.Conn, error), error) // Read a pending response from the server. This is necessary after completing a // data command since the server sends an unsolicited response you must read. ReadResponse() (int, string, error) // Close the control and data connection, if open. Close() error }