package upload import ( "context" "net/http" "os" "path/filepath" "strings" "qnc-server/app/main/api/internal/svc" "qnc-server/common/xerr" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" ) type ServeUploadLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewServeUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ServeUploadLogic { return &ServeUploadLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *ServeUploadLogic) ServeUpload(name string, w http.ResponseWriter) error { name = filepath.Base(strings.TrimSpace(name)) if name == "" || name == "." || name == ".." || !isSafeUploadFileName(name) { return errors.Wrapf(xerr.NewErrMsg("无效的文件名"), "") } fullPath := filepath.Join(uploadImageDir, name) data, err := os.ReadFile(fullPath) if err != nil { if os.IsNotExist(err) { return errors.Wrapf(xerr.NewErrMsg("文件不存在"), "") } return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "读取文件失败: %v", err) } w.Header().Set("Cache-Control", "public, max-age=86400") switch filepath.Ext(name) { case ".png": w.Header().Set("Content-Type", "image/png") case ".gif": w.Header().Set("Content-Type", "image/gif") case ".webp": w.Header().Set("Content-Type", "image/webp") default: w.Header().Set("Content-Type", "image/jpeg") } _, err = w.Write(data) return err } func isSafeUploadFileName(name string) bool { for _, c := range name { if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-' { continue } return false } return true }