You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

icon.go 3.3 kB

2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package badge
  2. import (
  3. "bytes"
  4. "code.gitea.io/gitea/models"
  5. "code.gitea.io/gitea/modules/base"
  6. "code.gitea.io/gitea/modules/setting"
  7. "crypto/md5"
  8. "errors"
  9. "fmt"
  10. "github.com/nfnt/resize"
  11. "github.com/oliamb/cutter"
  12. "image"
  13. "image/png"
  14. "io/ioutil"
  15. "mime/multipart"
  16. "os"
  17. )
  18. type IconUploader struct {
  19. Config IconUploadConfig
  20. }
  21. type IconUploadForm struct {
  22. Icon *multipart.FileHeader
  23. }
  24. type IconUploadConfig struct {
  25. FileMaxSize int64
  26. FileMaxWidth int
  27. FileMaxHeight int
  28. DefaultSize uint
  29. NeedResize bool
  30. NeedSquare bool
  31. }
  32. func NewIconUploader(config IconUploadConfig) IconUploader {
  33. return IconUploader{Config: config}
  34. }
  35. func (u IconUploader) Upload(form IconUploadForm, user *models.User) (string, error) {
  36. if form.Icon == nil || form.Icon.Filename == "" {
  37. return "", errors.New("File or fileName is empty")
  38. }
  39. fr, err := form.Icon.Open()
  40. if err != nil {
  41. return "", fmt.Errorf("Icon.Open: %v", err)
  42. }
  43. defer fr.Close()
  44. if form.Icon.Size > u.Config.FileMaxSize {
  45. return "", errors.New("File is too large")
  46. }
  47. data, err := ioutil.ReadAll(fr)
  48. if err != nil {
  49. return "", fmt.Errorf("ioutil.ReadAll: %v", err)
  50. }
  51. if !base.IsImageFile(data) {
  52. return "", errors.New("File is not a image")
  53. }
  54. iconName, err := u.uploadIcon(data, user.ID)
  55. if err != nil {
  56. return "", fmt.Errorf("uploadIcon: %v", err)
  57. }
  58. return iconName, nil
  59. }
  60. func (u IconUploader) uploadIcon(data []byte, userId int64) (string, error) {
  61. m, err := u.prepare(data)
  62. if err != nil {
  63. return "", err
  64. }
  65. iconName := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userId, md5.Sum(data)))))
  66. if err := os.MkdirAll(setting.IconUploadPath, os.ModePerm); err != nil {
  67. return "", fmt.Errorf("uploadIcon. Failed to create dir %s: %v", setting.AvatarUploadPath, err)
  68. }
  69. fw, err := os.Create(models.GetCustomIconByHash(iconName))
  70. if err != nil {
  71. return "", fmt.Errorf("Create: %v", err)
  72. }
  73. defer fw.Close()
  74. if err = png.Encode(fw, *m); err != nil {
  75. return "", fmt.Errorf("Encode: %v", err)
  76. }
  77. return iconName, nil
  78. }
  79. func (u IconUploader) prepare(data []byte) (*image.Image, error) {
  80. imgCfg, _, err := image.DecodeConfig(bytes.NewReader(data))
  81. if err != nil {
  82. return nil, fmt.Errorf("DecodeConfig: %v", err)
  83. }
  84. if imgCfg.Width > u.Config.FileMaxWidth {
  85. return nil, fmt.Errorf("Image width is too large: %d > %d", imgCfg.Width, setting.AvatarMaxWidth)
  86. }
  87. if imgCfg.Height > u.Config.FileMaxHeight {
  88. return nil, fmt.Errorf("Image height is too large: %d > %d", imgCfg.Height, setting.AvatarMaxHeight)
  89. }
  90. img, _, err := image.Decode(bytes.NewReader(data))
  91. if err != nil {
  92. return nil, fmt.Errorf("Decode: %v", err)
  93. }
  94. if u.Config.NeedSquare {
  95. if imgCfg.Width != imgCfg.Height {
  96. var newSize, ax, ay int
  97. if imgCfg.Width > imgCfg.Height {
  98. newSize = imgCfg.Height
  99. ax = (imgCfg.Width - imgCfg.Height) / 2
  100. } else {
  101. newSize = imgCfg.Width
  102. ay = (imgCfg.Height - imgCfg.Width) / 2
  103. }
  104. img, err = cutter.Crop(img, cutter.Config{
  105. Width: newSize,
  106. Height: newSize,
  107. Anchor: image.Point{ax, ay},
  108. })
  109. if err != nil {
  110. return nil, err
  111. }
  112. }
  113. }
  114. if u.Config.NeedResize && u.Config.DefaultSize > 0 {
  115. img = resize.Resize(u.Config.DefaultSize, u.Config.DefaultSize, img, resize.NearestNeighbor)
  116. }
  117. return &img, nil
  118. }