codesync.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package commutil
  2. import (
  3. "archive/zip"
  4. "bytes"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "mime/multipart"
  10. "net/http"
  11. "os"
  12. "path/filepath"
  13. sp "spiderutil"
  14. "strconv"
  15. "strings"
  16. )
  17. // 任务发布
  18. func publishModule(taskCode, scriptCode, params string, workStart, workEnd, workTimeout, interval int) (err error) {
  19. if workStart < 0 || workEnd < 0 || workStart > workEnd || workEnd > 23 {
  20. return errors.New("起始或结束时间异常!")
  21. } else {
  22. req, err := http.NewRequest("GET", fmt.Sprintf("%s/publish", sp.Config.TaskMgrSerever), nil)
  23. if err != nil {
  24. return errors.New("服务端链接创建失败!")
  25. }
  26. req.Header.Set("task_code", taskCode)
  27. req.Header.Set("script_code", scriptCode)
  28. req.Header.Set("work_start", strconv.Itoa(workStart))
  29. req.Header.Set("work_end", strconv.Itoa(workEnd))
  30. req.Header.Set("worktimeout", strconv.Itoa(workTimeout))
  31. req.Header.Set("interval", strconv.Itoa(interval))
  32. req.Header.Set("params", params)
  33. client := httpClient()
  34. resp, err := client.Do(req)
  35. if err != nil {
  36. return errors.New("服务端发布请求失败!")
  37. }
  38. defer resp.Body.Close()
  39. }
  40. return
  41. }
  42. // postModule 推送模块
  43. func postModule(path, module string) error {
  44. name := module
  45. bs, err := dir2Zip(path)
  46. if err != nil {
  47. return err
  48. }
  49. uploadUrl := fmt.Sprintf("%s/push", sp.Config.CodeDbSerever)
  50. // 创建一个 multipart.FormDataWriter
  51. body := bytes.NewBuffer(nil)
  52. writer := multipart.NewWriter(body)
  53. // 添加文件
  54. part, err := writer.CreateFormFile("file", "1.zip")
  55. if err != nil {
  56. return err
  57. }
  58. _, err = io.Copy(part, bytes.NewReader(bs))
  59. if err != nil {
  60. return err
  61. }
  62. // 添加表单数据
  63. err = writer.WriteField("name", name)
  64. if err != nil {
  65. return err
  66. }
  67. // 完成 multipart 插头
  68. err = writer.Close()
  69. if err != nil {
  70. return err
  71. }
  72. // 创建一个表示 multipart/form-data 的 http.Client
  73. client := httpClient()
  74. // 构建 POST 请求
  75. req, err := http.NewRequest("POST", uploadUrl, nil)
  76. if err != nil {
  77. return err
  78. }
  79. // 设置 Content-Type 为 multipart/form-data
  80. req.Header.Set("Content-Type", writer.FormDataContentType())
  81. // 设置请求体
  82. req.Body = ioutil.NopCloser(body)
  83. // 发送请求
  84. resp, err := client.Do(req)
  85. if err != nil {
  86. return err
  87. }
  88. defer resp.Body.Close()
  89. // 读取响应
  90. _, err = ioutil.ReadAll(resp.Body)
  91. return err
  92. }
  93. // unPubModule 撤销任务发布
  94. func unPubModule(taskCode string) error {
  95. req, err := http.NewRequest("GET", fmt.Sprintf("%s/unpublish", sp.Config.CodeDbSerever), nil)
  96. if err != nil {
  97. return err
  98. }
  99. req.Header.Add("task_code", taskCode)
  100. client := httpClient()
  101. resp, err := client.Do(req)
  102. if err != nil {
  103. return err
  104. }
  105. defer resp.Body.Close()
  106. return nil
  107. }
  108. // 压缩目录为zip文件
  109. func dir2Zip(srcPath string) (bs []byte, err error) {
  110. buf := bytes.NewBuffer(nil)
  111. zipWriter := zip.NewWriter(buf)
  112. // 遍历目录并添加文件到 ZIP 归档
  113. err = filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error {
  114. if err != nil {
  115. return err
  116. }
  117. // 跳过根目录
  118. if path == srcPath {
  119. return nil
  120. }
  121. // 计算相对于根目录的路径
  122. relPath, err := filepath.Rel(srcPath, path)
  123. if err != nil {
  124. return err
  125. }
  126. // 创建 ZIP 文件条目
  127. header, err := zip.FileInfoHeader(info)
  128. if err != nil {
  129. return err
  130. }
  131. // 设置文件条目的名称
  132. header.Name = relPath
  133. // 处理目录
  134. if info.IsDir() {
  135. header.Name += "/"
  136. } else {
  137. header.Method = zip.Deflate
  138. }
  139. // 写入 ZIP 文件条目
  140. writer, err := zipWriter.CreateHeader(header)
  141. if err != nil {
  142. return err
  143. }
  144. // 如果是文件,写入文件内容
  145. if !info.IsDir() {
  146. file, err := os.Open(path)
  147. if err != nil {
  148. return err
  149. }
  150. defer file.Close()
  151. _, err = io.Copy(writer, file)
  152. if err != nil {
  153. return err
  154. }
  155. zipWriter.Flush()
  156. }
  157. return nil
  158. })
  159. zipWriter.Close()
  160. bs = buf.Bytes()
  161. return
  162. }
  163. // pullModule 拉取模块
  164. func pullModule(path, module string) error {
  165. pullUrl := fmt.Sprintf("%s/pull", sp.Config.CodeDbSerever)
  166. client := httpClient()
  167. req, err := http.NewRequest("POST", pullUrl, strings.NewReader(fmt.Sprintf("%s=%s", "name", module)))
  168. if err != nil {
  169. return err
  170. }
  171. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  172. resp, err := client.Do(req)
  173. if err != nil {
  174. return err
  175. }
  176. version := resp.Header.Get("code-version")
  177. fmt.Println("version", version)
  178. bs, err := ioutil.ReadAll(resp.Body)
  179. if err != nil {
  180. return err
  181. }
  182. resp.Body.Close()
  183. //保存临时文件
  184. // os.WriteFile(fmt.Sprintf("%s_%s_%04d.zip", path,
  185. // time.Now().Format("20060102150405"),
  186. // rand.Intn(10000)), bs, 0777)
  187. //zip解压
  188. return unzip(bs, path)
  189. }
  190. // 解压缩zip文件到指定目录
  191. func unzip(zipData []byte, destDir string) error {
  192. // 打开 zip 文件
  193. r, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData)))
  194. if err != nil {
  195. return errors.New("open zipfile " + err.Error())
  196. }
  197. // 确保目标目录存在
  198. err = os.MkdirAll(destDir, 0755)
  199. if err != nil {
  200. return errors.New("open zipfile " + err.Error())
  201. }
  202. // 遍历 zip 文件中的所有条目
  203. for _, f := range r.File {
  204. // 打开文件
  205. func() error {
  206. rc, err := f.Open()
  207. if err != nil {
  208. return err
  209. }
  210. defer rc.Close()
  211. // 处理文件
  212. path := f.Name
  213. if path == "/" {
  214. return errors.New("skip root dir") // 跳过根目录
  215. }
  216. // 创建目标文件
  217. w, err := os.Create(destDir + "/" + path)
  218. if err != nil {
  219. return err
  220. }
  221. defer w.Close()
  222. // 复制文件内容
  223. _, err = io.Copy(w, rc)
  224. return err
  225. }()
  226. }
  227. return nil
  228. }