package upload import ( "context" "os" "path/filepath" "strings" "tyc-server/app/main/api/internal/svc" "tyc-server/app/main/api/internal/types" "tyc-server/common/xerr" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" ) type ServeUploadedFileLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewServeUploadedFileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ServeUploadedFileLogic { return &ServeUploadedFileLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *ServeUploadedFileLogic) ServeUploadedFile(req *types.ServeUploadedFileReq) (resp *types.ServeUploadedFileResp, err error) { fileName := strings.TrimSpace(req.FileName) if fileName == "" { return nil, errors.Wrap(xerr.NewErrMsg("缺少文件名"), "fileName empty") } // 只允许文件名,禁止路径穿越 if strings.Contains(fileName, "..") || filepath.Base(fileName) != fileName { return nil, errors.Wrap(xerr.NewErrMsg("非法文件名"), fileName) } candidates := []string{ "data/uploads", "../data/uploads", "../../data/uploads", "../../../data/uploads", } for _, c := range candidates { abs, _ := filepath.Abs(c) fullPath := filepath.Join(abs, fileName) if info, err := os.Stat(fullPath); err == nil && !info.IsDir() { contentType := "image/jpeg" if strings.HasSuffix(strings.ToLower(fileName), ".png") { contentType = "image/png" } else if strings.HasSuffix(strings.ToLower(fileName), ".gif") { contentType = "image/gif" } else if strings.HasSuffix(strings.ToLower(fileName), ".webp") { contentType = "image/webp" } return &types.ServeUploadedFileResp{ FilePath: fullPath, ContentType: contentType, }, nil } } return nil, errors.Wrapf(xerr.NewErrMsg("文件不存在"), "fileName=%s", fileName) }