新增 AddTypes、SetDefaultType、GetDefaultType 函数, 支持运行时动态配置 MIME 类型映射。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
98 lines
2.9 KiB
Go
98 lines
2.9 KiB
Go
// Package mimeutil 提供 MIME 类型检测工具函数。
|
||
//
|
||
// 该文件实现了基于文件扩展名的 MIME 类型检测,
|
||
// 补充 Go 标准库 mime 包中缺失或错误的映射。
|
||
//
|
||
// 主要功能:
|
||
// - 本地 MIME 映射:避免 mime.AddExtensionType 的全局副作用
|
||
// - 自动回退:未覆盖的扩展名回退到标准库
|
||
// - 大小写处理:自动将扩展名转为小写再查找
|
||
//
|
||
// 注意事项:
|
||
// - 使用包本地映射而非全局修改,确保多线程安全
|
||
// - 部分扩展名(如 .otf、.webm)Go 标准库返回错误类型,已在此纠正
|
||
//
|
||
// 作者:xfy
|
||
package mimeutil
|
||
|
||
import (
|
||
"mime"
|
||
"path/filepath"
|
||
"strings"
|
||
"sync"
|
||
)
|
||
|
||
// mimeOverrides 补充 Go 标准库缺失或错误的 MIME 类型映射。
|
||
// 使用包本地映射而非 mime.AddExtensionType,避免全局副作用。
|
||
//
|
||
// 注意: 部分扩展名 Go 返回错误类型而非缺失:
|
||
// - .otf: Go 映射到 OpenDocument 公式模板,应为字体格式
|
||
// - .webm: Go 返回 audio/webm,但 webm 可包含视频
|
||
var (
|
||
mimeOverrides = map[string]string{
|
||
".eot": "application/vnd.ms-fontobject", // 缺失
|
||
".otf": "font/otf", // Go 返回错误类型
|
||
".webmanifest": "application/manifest+json", // 缺失
|
||
".map": "application/json", // 缺失
|
||
".webm": "video/webm", // Go 返回 audio/webm
|
||
// 注意: Go 1.26.2+ 已正确支持 .mjs, .avif, .woff, .woff2
|
||
}
|
||
mimeMutex sync.RWMutex
|
||
|
||
defaultMIME = "application/octet-stream"
|
||
defaultMutex sync.RWMutex
|
||
)
|
||
|
||
// AddTypes 添加自定义 MIME 类型映射(线程安全)。
|
||
//
|
||
// 参数:
|
||
// - types: 扩展名到 MIME 类型的映射,扩展名会自动转为小写
|
||
func AddTypes(types map[string]string) {
|
||
mimeMutex.Lock()
|
||
defer mimeMutex.Unlock()
|
||
for ext, mime := range types {
|
||
mimeOverrides[strings.ToLower(ext)] = mime
|
||
}
|
||
}
|
||
|
||
// SetDefaultType 设置默认 MIME 类型(线程安全)。
|
||
//
|
||
// 参数:
|
||
// - defaultType: 默认 MIME 类型
|
||
func SetDefaultType(defaultType string) {
|
||
defaultMutex.Lock()
|
||
defer defaultMutex.Unlock()
|
||
defaultMIME = defaultType
|
||
}
|
||
|
||
// GetDefaultType 获取默认 MIME 类型(线程安全)。
|
||
//
|
||
// 返回值:
|
||
// - string: 当前默认 MIME 类型
|
||
func GetDefaultType() string {
|
||
defaultMutex.RLock()
|
||
defer defaultMutex.RUnlock()
|
||
return defaultMIME
|
||
}
|
||
|
||
// DetectContentType 检测文件的 MIME 类型。
|
||
//
|
||
// 优先使用包本地映射,回退到 Go 标准库 mime.TypeByExtension。
|
||
// 自动处理扩展名大小写问题。
|
||
//
|
||
// 参数:
|
||
// - filePath: 文件路径
|
||
//
|
||
// 返回值:
|
||
// - string: MIME 类型,未知类型返回空字符串
|
||
func DetectContentType(filePath string) string {
|
||
ext := strings.ToLower(filepath.Ext(filePath))
|
||
mimeMutex.RLock()
|
||
mimeType, ok := mimeOverrides[ext]
|
||
mimeMutex.RUnlock()
|
||
if ok {
|
||
return mimeType
|
||
}
|
||
return mime.TypeByExtension(ext)
|
||
}
|