feat(mimeutil): 添加 MIME 类型检测工具包
提供 DetectContentType 函数,补充 Go 标准库缺失的 MIME 类型映射。 使用包本地映射而非全局 mime.AddExtensionType,避免副作用。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
edf192ff85
commit
fdab778896
41
internal/mimeutil/detect.go
Normal file
41
internal/mimeutil/detect.go
Normal file
@ -0,0 +1,41 @@
|
||||
// Package mimeutil 提供 MIME 类型检测工具。
|
||||
package mimeutil
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// DetectContentType 检测文件的 MIME 类型。
|
||||
//
|
||||
// 优先使用包本地映射,回退到 Go 标准库 mime.TypeByExtension。
|
||||
// 自动处理扩展名大小写问题。
|
||||
//
|
||||
// 参数:
|
||||
// - filePath: 文件路径
|
||||
//
|
||||
// 返回值:
|
||||
// - string: MIME 类型,未知类型返回空字符串
|
||||
func DetectContentType(filePath string) string {
|
||||
ext := strings.ToLower(filepath.Ext(filePath))
|
||||
if mime, ok := mimeOverrides[ext]; ok {
|
||||
return mime
|
||||
}
|
||||
return mime.TypeByExtension(ext)
|
||||
}
|
||||
44
internal/mimeutil/detect_test.go
Normal file
44
internal/mimeutil/detect_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package mimeutil
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestDetectContentType 测试 MIME 类型检测
|
||||
func TestDetectContentType(t *testing.T) {
|
||||
tests := []struct {
|
||||
filePath string
|
||||
want string
|
||||
}{
|
||||
// 标准库已知类型 (验证回退)
|
||||
{"test.html", "text/html; charset=utf-8"},
|
||||
{"test.css", "text/css; charset=utf-8"},
|
||||
{"test.js", "text/javascript; charset=utf-8"},
|
||||
{"test.json", "application/json"},
|
||||
{"test.mjs", "text/javascript; charset=utf-8"}, // Go 1.26.2+ 已支持
|
||||
|
||||
// 包本地补充类型 - 缺失
|
||||
{"test.eot", "application/vnd.ms-fontobject"},
|
||||
{"test.webmanifest", "application/manifest+json"},
|
||||
{"test.map", "application/json"},
|
||||
|
||||
// 包本地覆盖类型 - Go 返回错误类型
|
||||
{"test.otf", "font/otf"}, // Go 返回 OpenDocument 公式模板
|
||||
{"test.webm", "video/webm"}, // Go 返回 audio/webm
|
||||
|
||||
// 大小写处理 - 验证 strings.ToLower
|
||||
{"test.EOT", "application/vnd.ms-fontobject"}, // 不在 Go 表中
|
||||
{"test.WEBMANIFEST", "application/manifest+json"},
|
||||
{"test.JPG", "image/jpeg"}, // Go 已知,也处理大小写
|
||||
|
||||
// 未知类型
|
||||
{"test.unknown", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.filePath, func(t *testing.T) {
|
||||
got := DetectContentType(tt.filePath)
|
||||
if got != tt.want {
|
||||
t.Errorf("DetectContentType(%q) = %q, want %q", tt.filePath, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user