file.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package services
  2. import (
  3. "bytes"
  4. "errors"
  5. "eta_gn/eta_api/models"
  6. "eta_gn/eta_api/utils"
  7. "fmt"
  8. "io"
  9. "mime/multipart"
  10. "os"
  11. "os/exec"
  12. "strings"
  13. "time"
  14. "github.com/pdfcpu/pdfcpu/pkg/api"
  15. "github.com/pdfcpu/pdfcpu/pkg/font"
  16. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
  17. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
  18. "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
  19. )
  20. func UploadToOssAndFileName(fileMulti multipart.File, newFileName string) (resourceUrl string, err error) {
  21. dateDir := time.Now().Format("20060102")
  22. uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
  23. err = os.MkdirAll(uploadDir, utils.DIR_MOD)
  24. if err != nil {
  25. err = errors.New("存储目录创建失败,Err:" + err.Error())
  26. return
  27. }
  28. fpath := uploadDir + "/" + newFileName
  29. err = saveToFile(fileMulti, fpath)
  30. if err != nil {
  31. err = errors.New("文件上传失败,Err:" + err.Error())
  32. return
  33. }
  34. ossClient := NewOssClient()
  35. if ossClient == nil {
  36. err = fmt.Errorf("初始化OSS服务失败")
  37. return
  38. }
  39. resourceUrl, err = ossClient.UploadFile(newFileName, fpath, "")
  40. if err != nil {
  41. err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
  42. return
  43. }
  44. defer func() {
  45. os.Remove(fpath)
  46. }()
  47. item := new(models.Resource)
  48. item.ResourceUrl = resourceUrl
  49. item.ResourceType = 1
  50. item.CreateTime = time.Now()
  51. _, err = models.AddResource(item)
  52. if err != nil {
  53. err = errors.New("资源上传失败,Err:" + err.Error())
  54. return
  55. }
  56. return
  57. }
  58. func saveToFile(fileMulti multipart.File, tofile string) error {
  59. f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  60. if err != nil {
  61. return err
  62. }
  63. defer f.Close()
  64. io.Copy(f, fileMulti)
  65. return nil
  66. }
  67. func GetResourceUrlBySvgImg(imgData string) (resourceUrl string, err error, errMsg string) {
  68. errMsg = "图表保存失败"
  69. uploadDir := "static/images/"
  70. if !utils.FileIsExist(uploadDir) {
  71. err = os.MkdirAll(uploadDir, utils.DIR_MOD)
  72. if err != nil {
  73. err = errors.New("存储目录创建失败,Err:" + err.Error())
  74. return
  75. }
  76. }
  77. randStr := utils.GetRandStringNoSpecialChar(28)
  78. var fileName, outFileName string
  79. fileName = randStr + ".txt"
  80. fileName = uploadDir + fileName
  81. err = utils.SaveToFile(imgData, fileName)
  82. if err != nil {
  83. err = errors.New("图片保存失败,Err:" + err.Error())
  84. return
  85. }
  86. defer func() {
  87. tmpErr := os.Remove(fileName)
  88. if tmpErr != nil {
  89. utils.FileLog.Info("删除临时存储的svg文件失败, err: " + tmpErr.Error())
  90. }
  91. }()
  92. outFileName = randStr + ".png"
  93. doneChannel := make(chan bool, 1)
  94. errorChannel := make(chan error, 1)
  95. cmd := exec.Command("highcharts-export-server", "--infile", fileName, "--constr", "Chart", "--scale", "2", "--workers", "10", "--workLimit", "3", "--outfile", outFileName)
  96. go func() {
  97. output, err := cmd.CombinedOutput()
  98. if err != nil {
  99. utils.FileLog.Info("execute command failed, output: , error: \n" + string(output) + err.Error())
  100. errorChannel <- err
  101. return
  102. }
  103. doneChannel <- true
  104. }()
  105. defer func() {
  106. tmpErr := os.Remove(outFileName)
  107. if tmpErr != nil {
  108. utils.FileLog.Info("删除生产的图片文件失败, err: " + tmpErr.Error())
  109. }
  110. }()
  111. select {
  112. case <-time.After(30 * time.Second):
  113. utils.FileLog.Info("执行超过30秒 杀死超时进程")
  114. e := cmd.Process.Kill()
  115. if e != nil {
  116. fmt.Println("cmd kill err: ", e.Error())
  117. utils.FileLog.Info(fmt.Sprintf("cmd kill err: %s", e.Error()))
  118. errMsg = "图片生成失败"
  119. err = errors.New("图片生成失败, 执行超时" + e.Error())
  120. return
  121. }
  122. fmt.Println("timeout kill process")
  123. case <-doneChannel:
  124. fmt.Println("done")
  125. case e := <-errorChannel:
  126. errMsg = "文件上传失败"
  127. err = errors.New(fmt.Sprintf("execute command failure err: %s", e.Error()))
  128. fmt.Println("execute command failure err:" + e.Error())
  129. return
  130. }
  131. ossClient := NewOssClient()
  132. if ossClient == nil {
  133. errMsg = "上传失败"
  134. err = errors.New("初始化OSS服务失败")
  135. return
  136. }
  137. resourceUrl, err = ossClient.UploadFile(outFileName, outFileName, "")
  138. if err != nil {
  139. errMsg = "文件上传失败"
  140. err = errors.New("文件上传失败,Err:" + err.Error())
  141. return
  142. }
  143. return
  144. }
  145. func GeneralWaterMarkPdf(pdfPath, waterMarkStr string) (f2 *bytes.Buffer, err error) {
  146. onTop := true
  147. update := false
  148. fontDir := `static`
  149. font.UserFontDir = fontDir
  150. ttfList := fontDir + `/SimHei.ttf`
  151. err = api.InstallFonts([]string{ttfList})
  152. if err != nil {
  153. fmt.Println("InstallFonts err:", err)
  154. }
  155. api.DisableConfigDir()
  156. f1, err := os.Open(pdfPath)
  157. if err != nil {
  158. fmt.Println("文件不存在")
  159. return
  160. }
  161. defer func() {
  162. _ = f1.Close()
  163. }()
  164. f2 = &bytes.Buffer{}
  165. strList := []string{waterMarkStr, waterMarkStr, waterMarkStr, waterMarkStr}
  166. newWaterMarkStr := strings.Join(strList, " ")
  167. wmList := make([]*model.Watermark, 0)
  168. for i := types.TopLeft; i <= 9; i++ {
  169. 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)
  170. if tmpErr != nil {
  171. fmt.Println("TextWatermark err:", tmpErr)
  172. return
  173. }
  174. wm.Pos = i
  175. wmList = append(wmList, wm)
  176. }
  177. err = AddWatermarks(f1, f2, nil, wmList, nil)
  178. return
  179. }
  180. func AddWatermarks(rs io.ReadSeeker, w io.Writer, selectedPages []string, wmList []*model.Watermark, conf *model.Configuration) error {
  181. if rs == nil {
  182. return errors.New("pdfcpu: AddWatermarks: missing rs")
  183. }
  184. if conf == nil {
  185. conf = model.NewDefaultConfiguration()
  186. }
  187. conf.Cmd = model.ADDWATERMARKS
  188. conf.OptimizeDuplicateContentStreams = false
  189. if len(wmList) <= 0 {
  190. return errors.New("pdfcpu: missing watermark configuration")
  191. }
  192. ctx, err := api.ReadValidateAndOptimize(rs, conf)
  193. if err != nil {
  194. return err
  195. }
  196. var pages types.IntSet
  197. pages, err = api.PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
  198. if err != nil {
  199. return err
  200. }
  201. for _, wm := range wmList {
  202. if err = pdfcpu.AddWatermarks(ctx, pages, wm); err != nil {
  203. return err
  204. }
  205. }
  206. return api.Write(ctx, w, conf)
  207. }