diff --git a/README.md b/README.md index 7fa8768..36b8ddc 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ You can find the docs at [go docs](https://pkg.go.dev/github.com/melbahja/goph). - Supports connections with **protected private keys** with passphrase. - Supports **upload** files from local to remote. - Supports **download** files from remote to local. +- Supports **writing** from `io.Reader` to remote file. +- Supports **reading** from remote file to `io.Writer`. - Supports connections with **ssh agent** (Unix systems only). - Supports adding new hosts to **known_hosts file**. - Supports **file system operations** like: `Open, Create, Chmod...` diff --git a/client.go b/client.go index 0e4267c..54440d1 100644 --- a/client.go +++ b/client.go @@ -168,46 +168,61 @@ func (c Client) Upload(localPath string, remotePath string) (err error) { } defer local.Close() - ftp, err := c.NewSftp() + return c.WriteFile(remotePath, local) +} + +// Download file from remote server! +func (c Client) Download(remotePath string, localPath string) (err error) { + + local, err := os.Create(localPath) if err != nil { return } - defer ftp.Close() + defer local.Close() - remote, err := ftp.Create(remotePath) + err = c.ReadFile(remotePath, local) if err != nil { - return + return err } - defer remote.Close() - _, err = io.Copy(remote, local) - return + return local.Sync() } -// Download file from remote server! -func (c Client) Download(remotePath string, localPath string) (err error) { +// WriteFile writes to a remote file +func (c Client) WriteFile(path string, data io.Reader) (err error) { + ftp, err := c.NewSftp() + if err != nil { + return + } + defer ftp.Close() - local, err := os.Create(localPath) + remote, err := ftp.Create(path) if err != nil { return } - defer local.Close() + defer remote.Close() + + _, err = io.Copy(remote, data) + return +} +// ReadFile reads from a remote file +func (c Client) ReadFile(path string, target io.Writer) (err error) { ftp, err := c.NewSftp() if err != nil { return } defer ftp.Close() - remote, err := ftp.Open(remotePath) + remote, err := ftp.Open(path) if err != nil { return } defer remote.Close() - if _, err = io.Copy(local, remote); err != nil { + if _, err = io.Copy(target, remote); err != nil { return } - return local.Sync() + return nil } diff --git a/examples/goph/main.go b/examples/goph/main.go index 25e8046..668dfa5 100644 --- a/examples/goph/main.go +++ b/examples/goph/main.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "bytes" "context" "errors" "flag" @@ -223,6 +224,8 @@ func playWithSSHJustForTestingThisProgram(client *goph.Client) { fmt.Println("Type your shell command and enter.") fmt.Println("To download file from remote type: download remote/path local/path") fmt.Println("To upload file to remote type: upload local/path remote/path") + fmt.Println("To read from remote file, type: read-file remote/path") + fmt.Println("To write to remote file, type: write-file remote/path file-contents") fmt.Println("To create a remote dir type: mkdirall /path/to/remote/newdir") fmt.Println("To exit type: exit") @@ -278,6 +281,37 @@ loop: fmt.Println("upload err: ", err) break + case "read-file": + if len(parts) != 2 { + fmt.Println("please provide a path to read from") + continue loop + } + + var target bytes.Buffer + err = client.ReadFile(parts[1], &target) + if err != nil { + fmt.Println("read file err: ", err) + } else { + fmt.Println(target.String()) + } + + break + + case "write-file": + if len(parts) != 3 { + fmt.Println("please provide a path to write to, and a text to write (no spaces)") + continue loop + } + + err = client.WriteFile(parts[1], strings.NewReader(parts[2])) + if err != nil { + fmt.Println("write file err: ", err) + } else { + fmt.Printf("text '%s' written to %s\n", parts[2], parts[1]) + } + + break + case "mkdirall": if len(parts) != 2 {