Skip to content

Commit

Permalink
refactor(uploader): improve file upload and download functionality su…
Browse files Browse the repository at this point in the history
…bpath constants

- Adjust file download
  • Loading branch information
LinkinStars committed Dec 4, 2024
1 parent c532114 commit 0d41ee9
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 41 deletions.
9 changes: 9 additions & 0 deletions internal/base/constant/upload.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package constant

const (
AvatarSubPath = "avatar"
AvatarThumbSubPath = "avatar_thumb"
PostSubPath = "post"
BrandingSubPath = "branding"
FilesPostSubPath = "files/post"
)
28 changes: 14 additions & 14 deletions internal/router/static_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package router

import (
"github.com/apache/incubator-answer/internal/base/constant"
"github.com/apache/incubator-answer/internal/service/service_config"
"github.com/gin-gonic/gin"
"path/filepath"
Expand All @@ -40,20 +41,19 @@ func NewStaticRouter(serviceConfig *service_config.ServiceConfig) *StaticRouter

// RegisterStaticRouter register static api router
func (a *StaticRouter) RegisterStaticRouter(r *gin.RouterGroup) {
r.Static("/uploads", a.serviceConfig.UploadPath)

r.GET("/download/*filepath", func(c *gin.Context) {
// The filePath such as /download/hash/123.png
r.Static("/uploads/"+constant.AvatarSubPath, filepath.Join(a.serviceConfig.UploadPath, constant.AvatarSubPath))
r.Static("/uploads/"+constant.AvatarThumbSubPath, filepath.Join(a.serviceConfig.UploadPath, constant.AvatarThumbSubPath))
r.Static("/uploads/"+constant.PostSubPath, filepath.Join(a.serviceConfig.UploadPath, constant.PostSubPath))
r.Static("/uploads/"+constant.BrandingSubPath, filepath.Join(a.serviceConfig.UploadPath, constant.BrandingSubPath))
r.GET("/uploads/"+constant.FilesPostSubPath+"/*filepath", func(c *gin.Context) {
// The filepath such as hash/123.pdf
filePath := c.Param("filepath")
// The download filename is 123.png
downloadFilename := filepath.Base(filePath)

// After trimming, the downloadLink is /uploads/hash
downloadLink := strings.TrimSuffix(filePath, "/"+downloadFilename)
// After add the extension, the downloadLink is /uploads/hash.png
downloadLink += filepath.Ext(downloadFilename)

downloadLink = filepath.Join(a.serviceConfig.UploadPath, downloadLink)
c.FileAttachment(downloadLink, downloadFilename)
// The original filename is 123.pdf
originalFilename := filepath.Base(filePath)
// The real filename is hash.pdf
realFilename := strings.TrimSuffix(filePath, "/"+originalFilename) + filepath.Ext(originalFilename)
// The file local path is /uploads/files/post/hash.pdf
fileLocalPath := filepath.Join(a.serviceConfig.UploadPath, constant.FilesPostSubPath, realFilename)
c.FileAttachment(fileLocalPath, originalFilename)
})
}
48 changes: 21 additions & 27 deletions internal/service/uploader/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"path/filepath"
"strings"

"github.com/apache/incubator-answer/internal/base/constant"
"github.com/apache/incubator-answer/internal/base/reason"
"github.com/apache/incubator-answer/internal/service/service_config"
"github.com/apache/incubator-answer/internal/service/siteinfo_common"
Expand All @@ -45,19 +46,13 @@ import (
"github.com/segmentfault/pacman/log"
)

const (
avatarSubPath = "avatar"
avatarThumbSubPath = "avatar_thumb"
postSubPath = "post"
brandingSubPath = "branding"
)

var (
subPathList = []string{
avatarSubPath,
avatarThumbSubPath,
postSubPath,
brandingSubPath,
constant.AvatarSubPath,
constant.AvatarThumbSubPath,
constant.PostSubPath,
constant.BrandingSubPath,
constant.FilesPostSubPath,
}
supportedThumbFileExtMapping = map[string]imaging.Format{
".jpg": imaging.JPEG,
Expand Down Expand Up @@ -123,27 +118,27 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context) (url string, err e
}

newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(avatarSubPath, newFilename)
avatarFilePath := path.Join(constant.AvatarSubPath, newFilename)
return us.uploadImageFile(ctx, fileHeader, avatarFilePath)
}

func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, size int) (url string, err error) {
fileSuffix := path.Ext(fileName)
if _, ok := supportedThumbFileExtMapping[fileSuffix]; !ok {
// if file type is not supported, return original file
return path.Join(us.serviceConfig.UploadPath, avatarSubPath, fileName), nil
return path.Join(us.serviceConfig.UploadPath, constant.AvatarSubPath, fileName), nil
}
if size > 1024 {
size = 1024
}

thumbFileName := fmt.Sprintf("%d_%d@%s", size, size, fileName)
thumbFilePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, avatarThumbSubPath, thumbFileName)
thumbFilePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, constant.AvatarThumbSubPath, thumbFileName)
avatarFile, err := os.ReadFile(thumbFilePath)
if err == nil {
return thumbFilePath, nil
}
filePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, avatarSubPath, fileName)
filePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath, constant.AvatarSubPath, fileName)
avatarFile, err = os.ReadFile(filePath)
if err != nil {
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
Expand All @@ -160,11 +155,11 @@ func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, si
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}

if err = dir.CreateDirIfNotExist(path.Join(us.serviceConfig.UploadPath, avatarThumbSubPath)); err != nil {
if err = dir.CreateDirIfNotExist(path.Join(us.serviceConfig.UploadPath, constant.AvatarThumbSubPath)); err != nil {
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}

avatarFilePath := path.Join(avatarThumbSubPath, thumbFileName)
avatarFilePath := path.Join(constant.AvatarThumbSubPath, thumbFileName)
saveFilePath := path.Join(us.serviceConfig.UploadPath, avatarFilePath)
out, err := os.Create(saveFilePath)
if err != nil {
Expand Down Expand Up @@ -206,7 +201,7 @@ func (us *uploaderService) UploadPostFile(ctx *gin.Context) (

fileExt := strings.ToLower(path.Ext(fileHeader.Filename))
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(postSubPath, newFilename)
avatarFilePath := path.Join(constant.PostSubPath, newFilename)
return us.uploadImageFile(ctx, fileHeader, avatarFilePath)
}

Expand Down Expand Up @@ -237,7 +232,7 @@ func (us *uploaderService) UploadPostAttachment(ctx *gin.Context) (

fileExt := strings.ToLower(path.Ext(fileHeader.Filename))
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(postSubPath, newFilename)
avatarFilePath := path.Join(constant.FilesPostSubPath, newFilename)
return us.uploadAttachmentFile(ctx, fileHeader, fileHeader.Filename, avatarFilePath)
}

Expand Down Expand Up @@ -268,7 +263,7 @@ func (us *uploaderService) UploadBrandingFile(ctx *gin.Context) (
}

newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(brandingSubPath, newFilename)
avatarFilePath := path.Join(constant.BrandingSubPath, newFilename)
return us.uploadImageFile(ctx, fileHeader, avatarFilePath)
}

Expand Down Expand Up @@ -316,15 +311,14 @@ func (us *uploaderService) uploadAttachmentFile(ctx *gin.Context, file *multipar
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}

// The original filename is 123.png
// The local saved path is /UploadPath/hash.png
// The download link wil be /download/hash/123.png.
// When downloading, the download link will be redirect to the local saved path. And the download filename will be 123.png.
ext := filepath.Ext(fileSubPath)
// Need url encode the original filename. Because the filename may contain special characters that conflict with the markdown syntax.
originalFilename = url.QueryEscape(originalFilename)
downloadPath := strings.TrimSuffix(fileSubPath, ext) + "/" + originalFilename
downloadUrl = fmt.Sprintf("%s/download/%s", siteGeneral.SiteUrl, downloadPath)

// The original filename is 123.pdf
// The local saved path is /UploadPath/hash.pdf
// When downloading, the download link will be redirect to the local saved path. And the download filename will be 123.png.
downloadPath := strings.TrimSuffix(fileSubPath, filepath.Ext(fileSubPath)) + "/" + originalFilename
downloadUrl = fmt.Sprintf("%s/uploads/%s", siteGeneral.SiteUrl, downloadPath)
return downloadUrl, nil
}

Expand Down

0 comments on commit 0d41ee9

Please sign in to comment.