upload.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/jlaffaye/ftp"
  12. )
  13. type version struct {
  14. Version string
  15. Cdn_dir string
  16. }
  17. type fileInfo struct {
  18. fullPath string
  19. relPath string
  20. }
  21. const PthSep = string(os.PathSeparator)
  22. var totalFileUploaded int
  23. var failList []fileInfo
  24. var delta_root_path string
  25. var cdn_dir string
  26. func loadVersion() string {
  27. d, err := os.ReadFile(config.Version_file)
  28. if err != nil {
  29. fmt.Printf("loadVersion failed %v\n", err)
  30. return ""
  31. }
  32. var v version
  33. err = json.Unmarshal(d, &v)
  34. if err != nil {
  35. fmt.Printf("loadVersion Unmarshal failed %v\n", err)
  36. return ""
  37. }
  38. cdn_dir = v.Cdn_dir
  39. vs := strings.Split(v.Version, ".")
  40. if len(vs) != 3 {
  41. fmt.Printf("loadVersion split version failed %s\n", v.Version)
  42. return ""
  43. }
  44. lv, _ := strconv.ParseInt(vs[len(vs)-1], 10, 32)
  45. lv--
  46. vs[len(vs)-1] = fmt.Sprintf("%d", lv)
  47. lastVersion := fmt.Sprintf("%v", vs[0])
  48. for i := 1; i < len(vs); i++ {
  49. lastVersion = fmt.Sprintf("%v.%v", lastVersion, vs[i])
  50. }
  51. fmt.Printf("loadVersion lastVersion = %s\n", lastVersion)
  52. return lastVersion
  53. }
  54. func doUpload() bool {
  55. totalFileUploaded = 0
  56. c, err := ftp.Dial(config.Ftp_url, ftp.DialWithTimeout(5*time.Second))
  57. if err != nil {
  58. fmt.Printf("doUpload 连接ftp服务器失败 %v\n", err)
  59. return false
  60. }
  61. err = c.Login(config.Ftp_user, config.Ftp_password)
  62. if err != nil {
  63. fmt.Printf("doUpload 登录ftp服务器失败 %v\n", err)
  64. return false
  65. }
  66. fmt.Printf("登录ftp完成\n")
  67. lastVersion := loadVersion()
  68. root_path := config.Delta_path + PthSep + lastVersion
  69. delta_root_path = root_path
  70. fmt.Printf("开始遍历delta目录 %s\n", root_path)
  71. uploadDir(root_path, "", c)
  72. loopCount := 0
  73. for {
  74. if len(failList) == 0 {
  75. break
  76. }
  77. loopCount++
  78. if loopCount > 10 {
  79. fmt.Printf("尝试上传失败文件达10次,退出 \n")
  80. return false
  81. }
  82. tmpFailed := make([]fileInfo, len(failList))
  83. copy(tmpFailed, failList)
  84. failList = []fileInfo{}
  85. fmt.Printf("正在上传失败文件 总共失败 %d \n", len(tmpFailed))
  86. for _, v := range tmpFailed {
  87. uploadFile(v.fullPath, v.relPath, c)
  88. }
  89. }
  90. fmt.Printf("上传完成,总共上传 %d 个文件 \n", totalFileUploaded)
  91. return totalFileUploaded > 0
  92. }
  93. func uploadDir(fullPath string, relPath string, c *ftp.ServerConn) {
  94. dir, err := os.ReadDir(fullPath)
  95. if err != nil {
  96. return
  97. }
  98. if relPath != "" {
  99. err := c.MakeDir(relPath)
  100. if err != nil && !strings.Contains(err.Error(), "exists") {
  101. fmt.Printf("uploadDir make dir failed %v path = %s\n", err, relPath)
  102. }
  103. }
  104. for _, fi := range dir {
  105. if fi.IsDir() { // 忽略目录
  106. uploadDir(fullPath+PthSep+fi.Name(), relPath+PthSep+fi.Name(), c)
  107. } else {
  108. uploadFile(fullPath+PthSep+fi.Name(), relPath+PthSep+fi.Name(), c)
  109. }
  110. }
  111. }
  112. func uploadFile(fullPath string, relPath string, c *ftp.ServerConn) {
  113. dat1, err1 := os.ReadFile(fullPath)
  114. if err1 != nil {
  115. fmt.Printf("uploadFile read file %s failed\n", fullPath)
  116. return
  117. }
  118. err := c.Stor(relPath, bytes.NewReader(dat1))
  119. if err != nil {
  120. fmt.Printf("uploadFile store failed %v relPath=%s\n", err, relPath)
  121. failList = append(failList, fileInfo{fullPath: fullPath, relPath: relPath})
  122. } else {
  123. fmt.Printf(" %s 已上传\n", relPath)
  124. totalFileUploaded++
  125. }
  126. }
  127. func flushCdn() {
  128. if cdn_dir == "" {
  129. return
  130. }
  131. fmt.Printf("正在覆盖cdn目录,%s -> %s \n", delta_root_path, cdn_dir)
  132. copyDir(delta_root_path, cdn_dir)
  133. }
  134. func copyFile(dstName, srcName string) (written int64, err error) {
  135. src, err := os.Open(srcName)
  136. if err != nil {
  137. fmt.Println("copy file " + srcName + " error")
  138. return
  139. }
  140. defer src.Close()
  141. os.Remove(dstName)
  142. dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
  143. if err != nil {
  144. fmt.Println("open file " + dstName + " error")
  145. return
  146. }
  147. defer dst.Close()
  148. //fmt.Println("copy file " + srcName + " to " + dstName)
  149. return io.Copy(dst, src)
  150. }
  151. func copyDir(srcPath string, destPath string) {
  152. os.MkdirAll(destPath, 0777)
  153. dir, err := os.ReadDir(srcPath)
  154. if err != nil {
  155. return
  156. }
  157. for _, fi := range dir {
  158. if fi.IsDir() { // 忽略目录
  159. outPath := destPath + PthSep + fi.Name()
  160. copyDir(srcPath+PthSep+fi.Name(), outPath)
  161. } else {
  162. srcFile := srcPath + PthSep + fi.Name()
  163. destFile := destPath + PthSep + fi.Name()
  164. copyFile(destFile, srcFile)
  165. }
  166. }
  167. }