Skip to content

Commit

Permalink
feat(file): implement file download functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
LinkinStars committed Dec 3, 2024
1 parent 3e92945 commit c532114
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
17 changes: 17 additions & 0 deletions internal/router/static_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ package router
import (
"github.com/apache/incubator-answer/internal/service/service_config"
"github.com/gin-gonic/gin"
"path/filepath"
"strings"
)

// StaticRouter static api router
Expand All @@ -39,4 +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
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)
})
}
19 changes: 14 additions & 5 deletions internal/service/uploader/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -237,7 +238,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)
return us.uploadAttachmentFile(ctx, fileHeader, avatarFilePath)
return us.uploadAttachmentFile(ctx, fileHeader, fileHeader.Filename, avatarFilePath)
}

func (us *uploaderService) UploadBrandingFile(ctx *gin.Context) (
Expand Down Expand Up @@ -304,8 +305,8 @@ func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.Fil
return url, nil
}

func (us *uploaderService) uploadAttachmentFile(ctx *gin.Context, file *multipart.FileHeader, fileSubPath string) (
url string, err error) {
func (us *uploaderService) uploadAttachmentFile(ctx *gin.Context, file *multipart.FileHeader, originalFilename, fileSubPath string) (
downloadUrl string, err error) {
siteGeneral, err := us.siteInfoService.GetSiteGeneral(ctx)
if err != nil {
return "", err
Expand All @@ -315,8 +316,16 @@ func (us *uploaderService) uploadAttachmentFile(ctx *gin.Context, file *multipar
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}

url = fmt.Sprintf("%s/uploads/%s", siteGeneral.SiteUrl, fileSubPath)
return url, nil
// 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)
return downloadUrl, nil
}

func (us *uploaderService) tryToUploadByPlugin(ctx *gin.Context, source plugin.UploadSource) (
Expand Down

0 comments on commit c532114

Please sign in to comment.