file.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. package services
  2. import (
  3. "bytes"
  4. "errors"
  5. "eta/eta_api/models"
  6. "eta/eta_api/utils"
  7. "fmt"
  8. "github.com/pdfcpu/pdfcpu/pkg/api"
  9. "github.com/pdfcpu/pdfcpu/pkg/font"
  10. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
  11. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
  12. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
  13. "io"
  14. "mime/multipart"
  15. "os"
  16. "os/exec"
  17. "strings"
  18. "time"
  19. )
  20. // UploadToOssAndFileName 上传到oss并使用这个名称
  21. func UploadToOssAndFileName(fileMulti multipart.File, newFileName string) (resourceUrl string, err error) {
  22. dateDir := time.Now().Format("20060102")
  23. uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
  24. err = os.MkdirAll(uploadDir, utils.DIR_MOD)
  25. if err != nil {
  26. err = errors.New("存储目录创建失败,Err:" + err.Error())
  27. return
  28. }
  29. //本地地址
  30. fpath := uploadDir + "/" + newFileName
  31. err = saveToFile(fileMulti, fpath)
  32. if err != nil {
  33. err = errors.New("文件上传失败,Err:" + err.Error())
  34. return
  35. }
  36. //上传到阿里云 和 minio
  37. //if utils.ObjectStorageClient == "minio" {
  38. // resourceUrl, err = UploadImgToMinIo(newFileName, fpath)
  39. // if err != nil {
  40. // err = errors.New("文件上传失败,Err:" + err.Error())
  41. // return
  42. // }
  43. //} else {
  44. // resourceUrl, err = UploadAliyunV2(newFileName, fpath)
  45. // if err != nil {
  46. // err = errors.New("文件上传失败,Err:" + err.Error())
  47. // return
  48. // }
  49. //}
  50. ossClient := NewOssClient()
  51. if ossClient == nil {
  52. err = fmt.Errorf("初始化OSS服务失败")
  53. return
  54. }
  55. resourceUrl, err = ossClient.UploadFile(newFileName, fpath, "")
  56. if err != nil {
  57. err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
  58. return
  59. }
  60. defer func() {
  61. os.Remove(fpath)
  62. }()
  63. item := new(models.Resource)
  64. item.ResourceUrl = resourceUrl
  65. item.ResourceType = 1
  66. item.CreateTime = time.Now()
  67. _, err = models.AddResource(item)
  68. if err != nil {
  69. err = errors.New("资源上传失败,Err:" + err.Error())
  70. return
  71. }
  72. return
  73. }
  74. // saveToFile 保存到本地文件
  75. func saveToFile(fileMulti multipart.File, tofile string) error {
  76. f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  77. if err != nil {
  78. return err
  79. }
  80. defer f.Close()
  81. io.Copy(f, fileMulti)
  82. return nil
  83. }
  84. func saveToFileByHeader(fileHeader *multipart.FileHeader, tofile string) error {
  85. src, err := fileHeader.Open()
  86. f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  87. if err != nil {
  88. return err
  89. }
  90. defer f.Close()
  91. io.Copy(f, src)
  92. return nil
  93. }
  94. // GetResourceUrlBySvgImg
  95. // @Description: 通过svg图片生成图片资源地址(传到OSS后的地址)
  96. // @author: Roc
  97. // @datetime 2024-07-16 10:18:09
  98. // @param imgData string
  99. // @return resourceUrl string
  100. // @return err error
  101. // @return errMsg string
  102. func GetResourceUrlBySvgImg(imgData string, backendGenerate ...bool) (resourceUrl string, err error, errMsg string) {
  103. errMsg = "图表保存失败"
  104. uploadDir := "static/images/"
  105. if !utils.FileIsExist(uploadDir) {
  106. err = os.MkdirAll(uploadDir, utils.DIR_MOD)
  107. if err != nil {
  108. err = errors.New("存储目录创建失败,Err:" + err.Error())
  109. return
  110. }
  111. }
  112. var fileName, outFileName string
  113. var generte bool
  114. uploadDir = "static/images/"
  115. randStr := utils.GetRandStringNoSpecialChar(28)
  116. outFileName = randStr + ".png"
  117. if len(backendGenerate) > 0 {
  118. generte = backendGenerate[0]
  119. }
  120. if !generte {
  121. err = utils.SaveBase64ToFile(imgData, outFileName)
  122. if err != nil {
  123. err = errors.New("图片保存失败,Err:" + err.Error())
  124. return
  125. }
  126. } else {
  127. //var saveToOssPath string
  128. fileName = randStr + ".txt"
  129. fileName = uploadDir + fileName
  130. err = utils.SaveToFile(imgData, fileName)
  131. if err != nil {
  132. err = errors.New("图片保存失败,Err:" + err.Error())
  133. return
  134. }
  135. // 删除临时存储的svg文件
  136. defer func() {
  137. err = os.Remove(fileName)
  138. if err != nil {
  139. utils.FileLog.Info("删除临时存储的svg文件失败, err: " + err.Error())
  140. }
  141. }()
  142. doneChannel := make(chan bool, 1)
  143. errorChannel := make(chan error, 1)
  144. cmd := exec.Command("highcharts-export-server", "--infile", fileName, "--constr", "Chart", "--scale", "2", "--workers", "10", "--workLimit", "3", "--outfile", outFileName)
  145. go func() {
  146. output, err := cmd.CombinedOutput()
  147. if err != nil {
  148. utils.FileLog.Info("execute command failed, output: , error: \n" + string(output) + err.Error())
  149. errorChannel <- err
  150. return
  151. }
  152. doneChannel <- true
  153. }()
  154. select {
  155. case <-time.After(30 * time.Second):
  156. utils.FileLog.Info("执行超过30秒 杀死超时进程")
  157. e := cmd.Process.Kill()
  158. if e != nil {
  159. fmt.Println("cmd kill err: ", e.Error())
  160. utils.FileLog.Info(fmt.Sprintf("cmd kill err: %s", e.Error()))
  161. errMsg = "图片生成失败"
  162. err = errors.New("图片生成失败, 执行超时" + e.Error())
  163. return
  164. }
  165. fmt.Println("timeout kill process")
  166. case <-doneChannel:
  167. fmt.Println("done")
  168. case e := <-errorChannel:
  169. errMsg = "文件上传失败"
  170. err = errors.New(fmt.Sprintf("execute command failure err: %s", e.Error()))
  171. fmt.Println("execute command failure err:" + e.Error())
  172. return
  173. }
  174. }
  175. defer func() {
  176. _ = os.Remove(outFileName)
  177. if err != nil {
  178. utils.FileLog.Info("删除生产的图片文件失败, err: " + err.Error())
  179. }
  180. }()
  181. //上传到阿里云 和 minio
  182. ossClient := NewOssClient()
  183. if ossClient == nil {
  184. errMsg = "上传失败"
  185. err = errors.New("初始化OSS服务失败")
  186. return
  187. }
  188. resourceUrl, err = ossClient.UploadFile(outFileName, outFileName, "")
  189. if err != nil {
  190. errMsg = "文件上传失败"
  191. err = errors.New("文件上传失败,Err:" + err.Error())
  192. return
  193. }
  194. return
  195. }
  196. func GeneralWaterMarkPdf(pdfPath, waterMarkStr string) (f2 *bytes.Buffer, err error) {
  197. onTop := true
  198. update := false
  199. //fontDir := `C:\Users\123\go\src\eta\eta_api\static`
  200. fontDir := `static`
  201. font.UserFontDir = fontDir
  202. ttfList := fontDir + `/SimHei.ttf`
  203. err = api.InstallFonts([]string{ttfList})
  204. if err != nil {
  205. fmt.Println("InstallFonts err:", err)
  206. }
  207. api.DisableConfigDir()
  208. f1, err := os.Open(pdfPath)
  209. if err != nil {
  210. fmt.Println("文件不存在")
  211. return
  212. }
  213. defer func() {
  214. _ = f1.Close()
  215. }()
  216. f2 = &bytes.Buffer{}
  217. //strList := []string{waterMarkStr, waterMarkStr, waterMarkStr, waterMarkStr, waterMarkStr, waterMarkStr}
  218. strList := []string{waterMarkStr, waterMarkStr, waterMarkStr, waterMarkStr}
  219. //strList := []string{waterMarkStr}
  220. newWaterMarkStr := strings.Join(strList, " ")
  221. wmList := make([]*model.Watermark, 0)
  222. for i := types.TopLeft; i <= 9; i++ {
  223. wm, tmpErr := api.TextWatermark(newWaterMarkStr, "fo:SimHei, points:48, col: 0.75 0.75 0.75, rot:45, scale:1 abs, opacity:0.3", onTop, update, types.POINTS)
  224. if tmpErr != nil {
  225. fmt.Println("TextWatermark err:", tmpErr)
  226. return
  227. }
  228. //wm.Pos = types.Center
  229. wm.Pos = i
  230. wmList = append(wmList, wm)
  231. }
  232. err = AddWatermarks(f1, f2, nil, wmList, nil)
  233. return
  234. }
  235. func AddWatermarks(rs io.ReadSeeker, w io.Writer, selectedPages []string, wmList []*model.Watermark, conf *model.Configuration) error {
  236. if rs == nil {
  237. return errors.New("pdfcpu: AddWatermarks: missing rs")
  238. }
  239. if conf == nil {
  240. conf = model.NewDefaultConfiguration()
  241. }
  242. conf.Cmd = model.ADDWATERMARKS
  243. conf.OptimizeDuplicateContentStreams = false
  244. if len(wmList) <= 0 {
  245. return errors.New("pdfcpu: missing watermark configuration")
  246. }
  247. ctx, err := api.ReadValidateAndOptimize(rs, conf)
  248. if err != nil {
  249. return err
  250. }
  251. var pages types.IntSet
  252. pages, err = api.PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
  253. if err != nil {
  254. return err
  255. }
  256. for _, wm := range wmList {
  257. if err = pdfcpu.AddWatermarks(ctx, pages, wm); err != nil {
  258. return err
  259. }
  260. }
  261. return api.Write(ctx, w, conf)
  262. }
  263. // CommonUploadToOssAndFileName 通用上传文件
  264. func CommonUploadToOssAndFileName(fileHeader *multipart.FileHeader, newFileName, savePath string) (resourceUrl string, err error) {
  265. dateDir := time.Now().Format("20060102")
  266. uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
  267. err = os.MkdirAll(uploadDir, utils.DIR_MOD)
  268. if err != nil {
  269. err = errors.New("存储目录创建失败,Err:" + err.Error())
  270. return
  271. }
  272. //本地地址
  273. fpath := uploadDir + "/" + newFileName
  274. err = saveToFileByHeader(fileHeader, fpath)
  275. if err != nil {
  276. err = errors.New("文件上传失败,Err:" + err.Error())
  277. return
  278. }
  279. ossClient := NewOssClient()
  280. if ossClient == nil {
  281. err = fmt.Errorf("初始化OSS服务失败")
  282. return
  283. }
  284. resourceUrl, err = ossClient.UploadFile(newFileName, fpath, savePath)
  285. if err != nil {
  286. err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
  287. return
  288. }
  289. defer func() {
  290. os.Remove(fpath)
  291. }()
  292. return
  293. }