file.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. package service
  2. import (
  3. "bufio"
  4. "context"
  5. "fmt"
  6. "io"
  7. "mime/multipart"
  8. "net/http"
  9. "os"
  10. "os/exec"
  11. "path"
  12. "path/filepath"
  13. "strings"
  14. "go-common/app/admin/ep/melloi/conf"
  15. "go-common/app/admin/ep/melloi/model"
  16. "go-common/library/ecode"
  17. "go-common/library/log"
  18. bm "go-common/library/net/http/blademaster"
  19. "github.com/pkg/errors"
  20. )
  21. // Upload upload file
  22. func (s *Service) Upload(c context.Context, uploadParam *model.UploadParam, formFile multipart.File, header *multipart.FileHeader) (id int, scriptPath string, err error) {
  23. var destFile *os.File
  24. //创建脚本保存路径
  25. if uploadParam.ScriptPath == "" {
  26. if scriptPath, err = s.uniqueFolderPath(uploadParam.Path); err != nil {
  27. return
  28. }
  29. } else {
  30. scriptPath = uploadParam.ScriptPath
  31. }
  32. //创建保存文件
  33. if destFile, err = os.Create(scriptPath + header.Filename); err != nil {
  34. log.Error("Create failed,error(%v)", err)
  35. return
  36. }
  37. defer destFile.Close()
  38. // 读取表单文件,写入保存文件
  39. if _, err = io.Copy(destFile, formFile); err != nil {
  40. log.Error("write file error (%v)", err)
  41. return
  42. }
  43. // jmx文件
  44. if strings.Contains(header.Filename, ".jmx") {
  45. treePath := model.TreePath{Department: uploadParam.Department, Project: uploadParam.Project, App: uploadParam.APP}
  46. script := model.Script{
  47. ProjectName: uploadParam.TestName,
  48. //TestName: uploadParam.TestName,
  49. SavePath: destFile.Name(),
  50. UpdateBy: uploadParam.UserName,
  51. TreePath: treePath,
  52. Upload: true,
  53. Active: 1,
  54. ResJtl: scriptPath + "jtl",
  55. JmeterLog: scriptPath + "jmg",
  56. ScriptPath: scriptPath,
  57. ArgumentString: "[{\"\":\"\"}]",
  58. TestType: 1,
  59. Domain: uploadParam.Domains,
  60. Fusing: uploadParam.Fusing,
  61. UseBusinessStop: uploadParam.UseBusinessStop,
  62. BusinessStopPercent: uploadParam.BusinessStopPercent,
  63. }
  64. if id, _, _, err = s.dao.AddScript(&script); err != nil {
  65. log.Error("s.dao.AddScript err :(%v)", err)
  66. return
  67. }
  68. }
  69. return
  70. }
  71. // UploadAndGetProtoInfo upload and get proto info
  72. func (s *Service) UploadAndGetProtoInfo(c context.Context, uploadParam *model.UploadParam, formFile multipart.File, header *multipart.FileHeader) (res map[string]interface{}, err error) {
  73. // 获取上传路径, Path 为root_path ,ScriptPath 为 root_path + import路径
  74. _, scriptPath, err := s.Upload(c, uploadParam, formFile, header)
  75. if err != nil {
  76. log.Error("Write file failed, error(%v)", err)
  77. return
  78. }
  79. // 解析proto文件
  80. path, fileName := filepath.Split(path.Join(scriptPath, header.Filename))
  81. if res, err = s.ProtoParsing(path, fileName); err != nil {
  82. log.Error("parser grpc error(%v)", err)
  83. return
  84. }
  85. // 生成import文件路径
  86. if err = s.CreateGRPCImportDir(res, uploadParam.Path); err != nil {
  87. return
  88. }
  89. return
  90. }
  91. // CreateGRPCImportDir create grpc import path
  92. func (s *Service) CreateGRPCImportDir(res map[string]interface{}, rootPath string) (err error) {
  93. if ipts, ok := res["import"]; ok {
  94. for _, ipt := range ipts.([]string) {
  95. iptPath, _ := filepath.Split(ipt)
  96. protoPath := &model.ProtoPathModel{RootPath: rootPath, ExtraPath: iptPath}
  97. if err = s.CreateProtoImportDir(protoPath); err != nil {
  98. log.Error("create proto import dir error(%v)", err)
  99. return
  100. }
  101. }
  102. }
  103. return
  104. }
  105. // CompileProtoFile compile proto file get jar path
  106. func (s *Service) CompileProtoFile(protoPath, filename string) (jarPath string, err error) {
  107. return s.createGrpcJar(protoPath, filename)
  108. }
  109. //protocFile protoc file
  110. func (s *Service) protocFile(scriptPath, protoPath string) (err error) {
  111. var (
  112. protoCMD string
  113. protoJava string
  114. protoFileList []string
  115. line string
  116. protoFiles = fmt.Sprintf("cd %s && find . -name '*.proto' | awk -F '\\.\\/' '{print $2}'", scriptPath)
  117. stdout io.ReadCloser
  118. )
  119. // 获取scriptPath 目录下所有 proto文件
  120. cmd := exec.Command("/bin/bash", "-c", protoFiles)
  121. if stdout, err = cmd.StdoutPipe(); err != nil {
  122. log.Error("run protoFiles (%s) error(%v)", protoFiles, err)
  123. return
  124. }
  125. cmd.Start()
  126. reader := bufio.NewReader(stdout)
  127. for {
  128. if line, err = reader.ReadString('\n'); err != nil || io.EOF == err {
  129. break
  130. }
  131. if line != "" {
  132. protoFileList = append(protoFileList, line)
  133. }
  134. }
  135. // 编译所有proto文件
  136. for _, line := range protoFileList {
  137. protoCMD = fmt.Sprintf("protoc -I %s --java_out=%s %s", scriptPath, protoPath, path.Join(scriptPath, line))
  138. protoJava = fmt.Sprintf("protoc --plugin=protoc-gen-grpc-java=%s --grpc-java_out=%s -I %s %s",
  139. s.c.Grpc.ProtoJavaPluginPath, protoPath, scriptPath, path.Join(scriptPath, line))
  140. if err = exec.Command("/bin/bash", "-c", protoCMD).Run(); err != nil {
  141. log.Error("protoc --proto_path (%s) error (%v)", protoCMD, err)
  142. return ecode.MelloiProtocError
  143. }
  144. // 编译所有proto文件
  145. for _, line := range protoFileList {
  146. protoCMD = fmt.Sprintf("protoc -I %s --java_out=%s %s", scriptPath, protoPath, path.Join(scriptPath, line))
  147. protoJava = fmt.Sprintf("protoc --plugin=protoc-gen-grpc-java=%s --grpc-java_out=%s -I %s %s",
  148. s.c.Grpc.ProtoJavaPluginPath, protoPath, scriptPath, path.Join(scriptPath, line))
  149. if err = exec.Command("/bin/bash", "-c", protoCMD).Run(); err != nil {
  150. log.Error("protoc --proto_path (%s) error (%v)", protoCMD, err)
  151. return ecode.MelloiProtocError
  152. }
  153. if err = exec.Command("/bin/bash", "-c", protoJava).Run(); err != nil {
  154. log.Error("protoc java (%s) error (%v)", protoCMD, err)
  155. return ecode.MelloiProtocError
  156. }
  157. }
  158. if err = exec.Command("/bin/bash", "-c", protoJava).Run(); err != nil {
  159. log.Error("protoc java (%s) error (%v)", protoCMD, err)
  160. return ecode.MelloiProtocError
  161. }
  162. }
  163. return
  164. }
  165. //createGrpcJar crate grpc jar
  166. func (s *Service) createGrpcJar(scriptPath, filename string) (jarPath string, err error) {
  167. protoPath := path.Join(scriptPath, "proto")
  168. if err = os.MkdirAll(protoPath, pathPerm); err != nil {
  169. log.Error("create proto path err ... (%v)", err)
  170. return
  171. }
  172. var (
  173. cmdJava = fmt.Sprintf(" cd %s && find . -name '*.java' |grep -v '^\\./\\.' > sources.txt ", protoPath)
  174. cmdJavac = fmt.Sprintf("cd %s && javac -Djava.ext.dirs=%s -encoding utf-8 @sources.txt ", protoPath, s.c.Jmeter.JmeterExtLibPath)
  175. jarFilename = strings.Replace(filename, ".proto", "", -1) + ".jar"
  176. cmdJar = fmt.Sprintf("cd %s && jar -cvf %s .", protoPath, jarFilename)
  177. )
  178. if err = s.protocFile(scriptPath, protoPath); err != nil {
  179. log.Error("protoc error (%v)", err)
  180. return
  181. }
  182. // 编译java文件
  183. if err = exec.Command("/bin/bash", "-c", cmdJava).Run(); err != nil {
  184. log.Error("find *.java (%s) error(%+v)", cmdJava, errors.WithStack(err))
  185. return
  186. }
  187. if err = exec.Command("/bin/bash", "-c", cmdJavac).Run(); err != nil {
  188. log.Error("javac protoc javac (%s) error(%v)", cmdJavac, err)
  189. err = ecode.MelloiJavacCompileError
  190. return
  191. }
  192. // 生成jar文件
  193. if err = exec.Command("/bin/bash", "-c", cmdJar).Run(); err != nil {
  194. log.Error("protoc jar (%s) error(%v)", cmdJar, err)
  195. err = ecode.MelloiJarError
  196. return
  197. }
  198. jarPath = path.Join(protoPath, jarFilename)
  199. return
  200. }
  201. //DownloadFile Download File
  202. func (s *Service) DownloadFile(c *bm.Context, filePath string, w http.ResponseWriter) (err error) {
  203. var (
  204. Fi *os.File
  205. info os.FileInfo
  206. )
  207. if info, err = os.Stat(filePath); err != nil {
  208. return
  209. }
  210. //如果文件太大,就禁止下载
  211. if info.Size() > conf.Conf.Melloi.MaxDowloadSize {
  212. err = ecode.MelloiBeyondFileSize
  213. return
  214. }
  215. if Fi, err = os.Open(filePath); err != nil {
  216. log.Error("open file err :(%v)", err)
  217. return
  218. }
  219. defer Fi.Close()
  220. w.Header().Set("Content-Disposition", "attachment; filename="+Fi.Name())
  221. if _, err = io.Copy(w, io.Reader(Fi)); err != nil {
  222. log.Error("copy file err :(%v)", err)
  223. err = ecode.MelloiCopyFileErr
  224. return
  225. }
  226. return
  227. }
  228. //ReadFile read file
  229. func (s *Service) ReadFile(c *bm.Context, file, limit string) (data string, err error) {
  230. var (
  231. info os.FileInfo
  232. buff []byte
  233. cmd *exec.Cmd
  234. )
  235. log.Info("开始读取文件--------- : (%s)", file)
  236. if info, err = os.Stat(file); err != nil {
  237. return
  238. }
  239. if info.Size() > conf.Conf.Melloi.MaxFileSize {
  240. cmd = exec.Command("/bin/bash", "-c", "tail -1500 "+file)
  241. } else {
  242. cmd = exec.Command("/bin/bash", "-c", "cat "+file)
  243. }
  244. buff, err = cmd.Output()
  245. if err != nil {
  246. return
  247. }
  248. data = string(buff)
  249. return
  250. }
  251. //IsFileExists is file exists
  252. func (s *Service) IsFileExists(c *bm.Context, fileName string) (bool, error) {
  253. return exists(fileName)
  254. }
  255. // exists exists
  256. func exists(path string) (bool, error) {
  257. _, err := os.Stat(path)
  258. if err == nil {
  259. return true, nil
  260. }
  261. if os.IsNotExist(err) {
  262. return false, nil
  263. }
  264. return false, err
  265. }