mw_file.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package middleware
  2. import (
  3. "bytes"
  4. "github.com/gogf/gf/net/ghttp"
  5. "github.com/nfnt/resize"
  6. "gxt-file-server/app/agent"
  7. "gxt-file-server/app/errors"
  8. "gxt-file-server/pkg/gplus"
  9. "gxt-file-server/pkg/logger"
  10. "image"
  11. "image/jpeg"
  12. "image/png"
  13. "net/url"
  14. "path"
  15. "strconv"
  16. "strings"
  17. )
  18. // FileMiddleWare 文件服务中间件
  19. func FileMiddleWare(skippers ...SkipperFunc) ghttp.HandlerFunc {
  20. return func(r *ghttp.Request) {
  21. if len(skippers) > 0 && skippers[0](r) {
  22. r.Middleware.Next()
  23. return
  24. }
  25. ctx := gplus.NewContext(r)
  26. filePath, err := url.PathUnescape(r.Request.URL.Path)
  27. if err != nil {
  28. logger.Errorf(ctx, err.Error())
  29. gplus.ResError(r, err)
  30. }
  31. var (
  32. thumb string
  33. w uint
  34. h uint
  35. )
  36. suffix := path.Ext(filePath)
  37. contentType := getContentType(suffix)
  38. fileData, _, err := agent.DefaultAgent().Get(ctx, filePath)
  39. if err != nil {
  40. gplus.ResError(r, errors.ErrFileNotFound)
  41. }
  42. thumb = r.GetString("thumb")
  43. if thumb == "1" && (contentType == "image/png" || contentType == "image/jpeg") {
  44. w = r.GetUint("w")
  45. h = r.GetUint("h")
  46. if w > 0 || h > 0 {
  47. img, format, err := image.Decode(bytes.NewBuffer(fileData))
  48. if err != nil {
  49. return
  50. }
  51. if origWidth := uint(img.Bounds().Dx()); w > origWidth {
  52. w = origWidth
  53. }
  54. if origHeight := uint(img.Bounds().Dy()); h > origHeight {
  55. h = origHeight
  56. }
  57. img = resize.Resize(w, h, img, resize.Lanczos3)
  58. buf := new(bytes.Buffer)
  59. if format == "png" {
  60. png.Encode(buf, img)
  61. } else {
  62. jpeg.Encode(buf, img, nil)
  63. }
  64. if l := buf.Len(); l > 0 {
  65. fileData = buf.Bytes()
  66. }
  67. }
  68. }
  69. if strings.HasPrefix(contentType, "text/html") ||
  70. strings.HasPrefix(contentType, "application/javascript") {
  71. contentType = "text/plain; charset=utf-8"
  72. }
  73. rangeParam := r.Request.Header.Get("Range")
  74. if rangeParam != "" {
  75. byteRanges := strings.Split(rangeParam, "=")
  76. if len(byteRanges) == 2 {
  77. ranges := strings.Split(byteRanges[1], "-")
  78. if len(ranges) == 2 {
  79. start, _ := strconv.Atoi(ranges[0])
  80. end, _ := strconv.Atoi(ranges[1])
  81. length := end - start + 1
  82. if start >= 0 || end > start {
  83. fileData = fileData[start:(start + length)]
  84. }
  85. }
  86. }
  87. }
  88. r.Response.Header().Set("Content-Type", contentType)
  89. r.Response.Header().Set("Cache-Control", "max-age=31536000")
  90. r.Response.Header().Set("Content-Length", strconv.FormatInt(int64(len(fileData)), 10))
  91. r.Response.Write(fileData)
  92. }
  93. }
  94. func getContentType(suffix string) string {
  95. fileContentType := make(map[string]string)
  96. fileContentType[".jpg"] = "image/jpeg"
  97. fileContentType[".jpeg"] = "image/jpeg"
  98. fileContentType[".gif"] = "image/gif"
  99. fileContentType[".png"] = "image/png"
  100. fileContentType[".mp4"] = "video/mp4"
  101. fileContentType[".mpg4"] = "video/mp4"
  102. fileContentType[".pdf"] = "application/pdf"
  103. fileContentType[".svg"] = "image/svg+xml"
  104. if r, ok := fileContentType[suffix]; ok {
  105. return r
  106. }
  107. return "application/octet-stream"
  108. }