ftp.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package ftp
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "time"
  11. "go-common/library/log"
  12. "github.com/ftp-master"
  13. )
  14. const (
  15. _ftpRetry = 3
  16. errFormat = "Func:[%s] - Step:[%s] - Error:[%v]"
  17. _sleep = 100 * time.Millisecond
  18. )
  19. // Retry . retry one function until no error
  20. func Retry(callback func() error, retry int, sleep time.Duration) (err error) {
  21. for i := 0; i < retry; i++ {
  22. if err = callback(); err == nil {
  23. return
  24. }
  25. time.Sleep(sleep)
  26. }
  27. return
  28. }
  29. // FileMd5 calculates the local file's md5 and store it in a file
  30. func (d *Dao) FileMd5(path string, md5Path string) (err error) {
  31. var (
  32. content []byte
  33. )
  34. if content, err = ioutil.ReadFile(path); err != nil {
  35. log.Error(errFormat+" FilePath: %s", "fileMd5", "ReadFile", err, path)
  36. return
  37. }
  38. md5hash := md5.New()
  39. if _, err = io.Copy(md5hash, bytes.NewReader(content)); err != nil {
  40. log.Error(errFormat, "fileMd5", "CopyContent", err)
  41. return
  42. }
  43. md5 := md5hash.Sum(nil)
  44. fMd5 := hex.EncodeToString(md5[:])
  45. file, error := os.OpenFile(md5Path, os.O_RDWR|os.O_CREATE, 0766)
  46. if error != nil {
  47. log.Error(errFormat, "fileMd5", "OpenFile", err)
  48. return
  49. }
  50. file.WriteString(fMd5)
  51. file.Close()
  52. return
  53. }
  54. // UploadFile the file to remote frp server and update the md5 file
  55. func (d *Dao) UploadFile(localPath string, remotePath string, url string) (err error) {
  56. var (
  57. ftpInfo = d.conf.Search.FTP
  58. c *ftp.ServerConn
  59. content []byte // file's content
  60. fileSize int64
  61. )
  62. // Dial
  63. if c, err = ftp.DialTimeout(ftpInfo.Host, time.Duration(ftpInfo.Timeout)); err != nil {
  64. log.Error(errFormat, "uploadFile", "DialTimeout", err)
  65. return
  66. }
  67. // use EPSV or not
  68. if !ftpInfo.UseEPSV {
  69. c.DisableEPSV = true
  70. }
  71. // Login
  72. if err = c.Login(ftpInfo.User, ftpInfo.Pass); err != nil {
  73. log.Error(errFormat, "uploadFile", "Login", err)
  74. return
  75. }
  76. // Change dir
  77. if err = c.ChangeDir(url); err != nil {
  78. log.Error(errFormat, "uploadFile", "ChangeDir", err)
  79. return
  80. }
  81. // Upload the file
  82. if content, err = ioutil.ReadFile(localPath); err != nil {
  83. log.Error(errFormat, "uploadFile", "ReadFile", err)
  84. return
  85. }
  86. data := bytes.NewBuffer(content)
  87. if err = Retry(func() (err error) {
  88. return c.Stor(remotePath, data)
  89. }, _ftpRetry, _sleep); err != nil {
  90. log.Error("upArchives Error %+v", err)
  91. return
  92. }
  93. // Calculate the file size to check it's ok
  94. if fileSize, err = c.FileSize(remotePath); err != nil {
  95. log.Error(errFormat, "uploadFile", "FileSize", err)
  96. return
  97. }
  98. if localSize := int64(len(content)); localSize != fileSize {
  99. err = fmt.Errorf("LocalSize is %d, RemoteSize is %d", localSize, fileSize)
  100. log.Error(errFormat, "uploadFile", "FileSize", err)
  101. return
  102. }
  103. log.Info("File %s is uploaded successfully, size: %d", remotePath, fileSize)
  104. return
  105. }