upfile_controllers.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package controllers
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "mime/multipart"
  7. "net/http"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "time"
  12. "xugu_license/internal/global"
  13. "xugu_license/internal/models"
  14. "xugu_license/internal/module/xlsx"
  15. "xugu_license/internal/utils"
  16. "github.com/gin-gonic/gin"
  17. )
  18. type fileInfo struct {
  19. fileName string
  20. fileSize int64
  21. fileMd5 string
  22. buf *os.File
  23. mf *multipart.File
  24. }
  25. func UploadfileHandler(c *gin.Context) {
  26. userAny, exists := c.Get("userInfo")
  27. if !exists {
  28. c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
  29. c.Abort()
  30. return
  31. }
  32. userInfo := userAny.(*models.UserInfo)
  33. //接收文件 //检查文件
  34. file, err := checkUploadFile(c)
  35. if err != nil {
  36. global.Logger.Errorln("检测上传文件不为xlsx格式 ", err.Error())
  37. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("检测上传文件不为xlsx格式: ", err.Error())})
  38. return
  39. }
  40. //保存文件
  41. saveFile(file)
  42. //解析文件
  43. lics, err := xlsx.XlsxController(file.mf)
  44. if err != nil {
  45. global.Logger.Errorln("解析文件失败 ", err.Error())
  46. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("解析文件失败: ", err.Error())})
  47. return
  48. }
  49. //插入数据到数据库
  50. for _, lic := range lics {
  51. err = models.InsertLicenseApplicationAndInfoRow(lic, userInfo.Id, userInfo.Username)
  52. if err != nil {
  53. global.Logger.Errorln("插入数据失败 ", err.Error())
  54. c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("插入数据失败: ", err.Error())})
  55. return
  56. }
  57. }
  58. //生成license
  59. // for _, lic := range lics {
  60. // pI := license.ProjectInfo{
  61. // ProjectName: lic.ProductName,
  62. // UserName: lic.AssociatedProject,
  63. // UserAddr: "",
  64. // SerialNumber: "",
  65. // }
  66. // eI := license.EnvironmentInfo{
  67. // CpuSN: "",
  68. // BaseboardSN: "",
  69. // MacAddr: lic.MasterMacAddress,
  70. // DiskID: "",
  71. // IPAddr: "",
  72. // }
  73. // //判断license类型
  74. // LicType := utils.SwitchLicenseType(lic.Version)
  75. // lI := license.LicenseInfo{
  76. // GenDate: "2024-07-15",
  77. // ExpireDate: "9999-12-31",
  78. // LicenseType: LicType,
  79. // LicenseVersion: 1,
  80. // HardType: 3,
  81. // }
  82. // licStr := license.GenerateLicense(pI, eI, lI)
  83. // fmt.Println("生成的license为:", licStr)
  84. // //生成副主节点license
  85. // var licStr2 []byte
  86. // if lic.SecondaryMasterMacAddress != "" {
  87. // eI.MacAddr = lic.SecondaryMasterMacAddress
  88. // licStr2 = license.GenerateLicense(pI, eI, lI)
  89. // }
  90. // xlsx.ExcelToMail(lic, licStr, licStr2)
  91. // }
  92. file.buf.Close()
  93. }
  94. // UploadFile 处理文件上传
  95. func checkUploadFile(c *gin.Context) (*fileInfo, error) {
  96. // 获取上传的文件
  97. file, err := c.FormFile("file")
  98. if err != nil {
  99. global.Logger.Errorln("未收到文件 ", err.Error())
  100. c.JSON(http.StatusBadRequest, gin.H{"error": "服务器未收到文件"})
  101. return nil, err
  102. }
  103. // 检查文件扩展名是否为xlsx
  104. ext := strings.ToLower(filepath.Ext(file.Filename))
  105. if ext != ".xlsx" {
  106. global.Logger.Errorln("文件格式不为xlsx ", err.Error())
  107. c.JSON(http.StatusBadRequest, gin.H{"error": "Only .xlsx files are allowed"})
  108. return nil, err
  109. }
  110. // 获取客户端发送的 MD5 值
  111. clientMd5 := c.PostForm("md5")
  112. if clientMd5 == "" {
  113. global.Logger.Errorln("md5不存在 ")
  114. c.JSON(http.StatusBadRequest, gin.H{"error": "MD5 value is required"})
  115. return nil, err
  116. }
  117. // 计算文件的 MD5 值
  118. fileMd5, err := utils.CalculateFileHeaderMd5(file)
  119. if err != nil {
  120. global.Logger.Errorln("计算文件md5失败 ", err.Error())
  121. c.JSON(http.StatusInternalServerError, gin.H{"error": "Unable to calculate MD5"})
  122. return nil, err
  123. }
  124. // 比较 MD5 值
  125. if fileMd5 != clientMd5 {
  126. // 删除保存的文件
  127. //os.Remove(filePath)
  128. global.Logger.Errorln("文件md5不一致 ")
  129. c.JSON(http.StatusBadRequest, gin.H{"error": "MD5 mismatch"})
  130. return nil, err
  131. }
  132. // 将 *multipart.FileHeader 转换为 *os.File
  133. tempFile, err := fileHeaderToOsFile(file)
  134. if err != nil {
  135. global.Logger.Errorln(" *multipart.FileHeader 转换为 *os.File 失败")
  136. c.JSON(http.StatusInternalServerError, gin.H{"error": "Unable to convert uploaded file to *os.File"})
  137. return nil, err
  138. }
  139. //defer tempFile.Close()
  140. c.JSON(http.StatusOK, gin.H{"message": "File uploaded successfully", "file": file.Filename})
  141. src, err := file.Open()
  142. if err != nil {
  143. global.Logger.Errorln("src, err := file.Open()失败 ", err.Error())
  144. return nil, err
  145. }
  146. return &fileInfo{fileName: file.Filename, fileSize: file.Size, fileMd5: fileMd5, buf: tempFile, mf: &src}, nil
  147. }
  148. // 保存文件
  149. func saveFile(file *fileInfo) error {
  150. // 确保保存文件的目录存在
  151. saveDir := "files"
  152. if err := os.MkdirAll(saveDir, os.ModePerm); err != nil {
  153. log.Fatal(err)
  154. }
  155. // 生成新的文件名
  156. originalFileName := file.fileName
  157. ext := filepath.Ext(originalFileName)
  158. name := strings.TrimSuffix(originalFileName, ext)
  159. timestamp := time.Now().Format("20060102_150405")
  160. newFileName := utils.GenerateFileName(name, timestamp, ext)
  161. filePath := filepath.Join(saveDir, newFileName)
  162. // 保存文件
  163. // 创建目标文件
  164. dst, err := os.Create(filePath)
  165. if err != nil {
  166. global.Logger.Errorln("创建文件失败", err.Error())
  167. return err
  168. }
  169. defer dst.Close()
  170. // 将内容从 src 复制到 dst
  171. fmt.Println("file.buf", file.buf)
  172. if _, err := io.Copy(dst, file.buf); err != nil {
  173. global.Logger.Errorln("内容从 src 复制到 dst", err.Error())
  174. return err
  175. }
  176. return nil
  177. }
  178. // fileHeaderToOsFile 将 *multipart.FileHeader 转换为 *os.File
  179. func fileHeaderToOsFile(fileHeader *multipart.FileHeader) (*os.File, error) {
  180. src, err := fileHeader.Open()
  181. if err != nil {
  182. global.Logger.Errorln("*multipart.FileHeader 转换为 *os.File失败", err.Error())
  183. return nil, err
  184. }
  185. defer src.Close()
  186. // 创建临时文件
  187. tempFile, err := os.CreateTemp("", "upload-*.xlsx")
  188. if err != nil {
  189. global.Logger.Errorln("创建临时文件失败", err.Error())
  190. return nil, err
  191. }
  192. // 将内容从 src 复制到 tempFile
  193. if _, err := io.Copy(tempFile, src); err != nil {
  194. global.Logger.Errorln("内容从 src 复制到 tempFile失败", err.Error())
  195. tempFile.Close()
  196. return nil, err
  197. }
  198. // 将文件指针移回文件开头
  199. if _, err := tempFile.Seek(0, 0); err != nil {
  200. tempFile.Close()
  201. global.Logger.Errorln("将文件指针移回文件开头失败", err.Error())
  202. return nil, err
  203. }
  204. return tempFile, nil
  205. }