go实现ftp

 
package ftp

import (
   "errors"
   "fmt"
   "io"
   "net"
   "os"
   "strconv"
   "strings"
)

type Ftp struct {
   con net.Conn
   ip  string
}

func NewFtp(ip string) (*Ftp, error) {
   buf := make([]byte, 1024)
   con, err := net.Dial("tcp", ip)
   if err != nil {
      return nil, err
   }
   n, err := con.Read(buf)
   if err != nil {
      return nil, err
   }
   fmt.Println(string(buf[:n]))
   return &Ftp{con, ip}, nil
}

func (self *Ftp) Login(user, pass string) error {
   buf := make([]byte, 1024)
   self.con.Write([]byte(fmt.Sprintf("USER %s\r\n", user)))
   self.con.Read(buf)
   self.con.Write([]byte(fmt.Sprintf("PASS %s\r\n", pass)))
   n, err := self.con.Read(buf)
   if err != nil {
      return err
   }
   if !strings.Contains(string(buf[:n]), "230 Logged on") {
      return errors.New(strings.TrimSpace(string(buf)))
   }
   return nil
}

func (self *Ftp) PutPasv(Pathname string) error {
   con, err := self.connection("STOR", Pathname)
   if err != nil {
      return err
   }
   File, err := os.Open(Pathname)
   if err != nil {
      con.Close()
      return err
   }
   io.Copy(con, File)
   File.Close()
   con.Close()
   buf := make([]byte, 1024)
   _, err = self.con.Read(buf)
   if err != nil {
      return err
   }
   return nil
}
func (self *Ftp) GetFile(Pathname string) error {
   con, err := self.connection("RETR", Pathname)
   if err != nil {
      return err
   }
   File, err := os.Create(Pathname)
   if err != nil {
      con.Close()
      return err
   }
   io.Copy(File, con)
   File.Close()
   con.Close()
   buf := make([]byte, 1024)
   _, err = self.con.Read(buf)
   if err != nil {
      return err
   }
   return nil
}
func (self *Ftp) connection(status, Pathname string) (net.Conn, error) {
   buf := make([]byte, 1024)
   self.con.Write([]byte("PASV \r\n"))
   n, err := self.con.Read(buf)
   if err != nil {
      return nil, err
   }
   if s := string(buf[:n]); !strings.Contains(s, "227 Entering Passive Mode") {
      return nil, errors.New(s)
   }
   port := getport(buf[27 : n-3])
   con, err := net.Dial("tcp", fmt.Sprintf("%s:%d", strings.Split(self.ip, ":")[0], port))
   if err != nil {
      return nil, err
   }
   self.con.Write([]byte(fmt.Sprintf("%s %s\r\n", status, Pathname)))
   n, err = self.con.Read(buf)
   if err != nil {
      con.Close()
      return nil, err
   }
   if !strings.Contains(string(buf[:n]), "150 Opening data channel") {
      con.Close()
      return nil, errors.New("create data link error.")
   }
   return con, nil
}

func getport(by []byte) int {
   s := string(by)
   list := strings.Split(s, ",")
   n1, err := strconv.Atoi(list[len(list)-2])
   if err != nil {
      return 0
   }
   n2, err := strconv.Atoi(list[len(list)-1])
   if err != nil {
      return 0
   }
   return n1*256 + n2
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值