// Copyright 2022 E99p1ant. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package storage import ( "fmt" "path/filepath" "strings" "time" ) // PictureKeyPrefix 是图片对象 key 的前缀。生产环境图片以无前缀方式存于 // bucket 根下(R2 PathStyle 下 bucket 名自动作为 URL 首段),故这里置空。 const PictureKeyPrefix = "" // uploadKey 按生产口径生成对象 key:`YYYY/MM/`。 // 无前缀、无 day 层,文件名用纳秒时间戳保证唯一,扩展名与最终落盘内容类型一致。 func uploadKey(ext string) string { now := time.Now() return fmt.Sprintf("%s%d/%02d/%d%s", PictureKeyPrefix, now.Year(), int(now.Month()), now.UnixNano(), ext) } // extFromContentType 由 MIME 类型推导扩展名,用于保证对象 key 的扩展名 // 与 ContentType(以及实际落盘字节)严格一致,避免出现「.jpg 实为 webp」的错配。 func extFromContentType(contentType string) string { switch contentType { case "image/jpeg": return ".jpg" case "image/png": return ".png" case "image/gif": return ".gif" case "image/webp": return ".webp" default: return "" } } // originalExt 取原始文件名的扩展名,统一转小写。用于转换失败回退原图时 // 保留原始扩展名(与生产口径一致)。 func originalExt(filename string) string { return strings.ToLower(filepath.Ext(filename)) } // MaxAvatarSize is the max avatar size which is 2MB. const MaxAvatarSize = 2 * 1024 * 1024 // MaxBackgroundSize is the max background size which is 2MB. const MaxBackgroundSize = 2 * 1024 * 1024