Golang 源码解析 DetectContentType 检测文件类型
我们可以使用 golang 中的 net/http 包的来查找文件的内容类型或 mime 类型。
DetectContentType 函数实现了 http://mimesniff.spec.whatwg.org/ 描述的算法,用于确定数据的 Content-Type .
该函数会检查数据的前 512 字节,然后返回一个合法的 MIME 类型,例如 application/json 或类似 image/jpg .
如果不能确定数据的类型,将返回 "application/octet-stream" .
为此,我们打开文件并读取前512个字节,
package main
import (
"os"
"fmt"
"net/http"
)
func main() {
// Open File
f, err := os.Open("test.pdf")
if err != nil {
panic(err)
}
defer f.Close()
// Get the content
contentType, err := GetFileContentType(f)
if err != nil {
panic(err)
}
fmt.Println("Content Type: " + contentType)
}
func GetFileContentType(out *os.File) (string, error) {
// 仅使用前512个字节来检测内容类型。
buffer := make([]byte, 512)
_, err := out.Read(buffer)
if err != nil {
return "", err
}
// 使用 net/http 包中的的DectectContentType函数,它将始终返回有效的 MIME 类型
// 对于没有匹配的未知类型,将返回 "application/octet-stream"
contentType := http.DetectContentType(buffer)
return contentType, nil
}
DetectContentType 函数源码
package http
import (
"bytes"
"encoding/binary"
)
// The algorithm uses at most sniffLen bytes to make its decision.
const sniffLen = 512
// DetectContentType implements the algorithm described
// at https://mimesniff.spec.whatwg.org/ to determine the
// Content-Type of the given data. It considers at most the
// first 512 bytes of data. DetectContentType always returns
// a valid MIME type: if it cannot determine a more specific one, it
// returns "application/octet-stream".
func DetectContentType(data []byte) string {
if len(data) > sniffLen {
data = data[:sniffLen]
}
// Index of the first non-whitespace byte in data.
firstNonWS := 0
for ; firstNonWS < len(data) && isWS(data[firstNonWS]); firstNonWS++ {
}
for _, sig := range sniffSignatures {
if ct := sig.match(data, firstNonWS); ct != "" {
return ct
}
}
return "application/octet-stream" // fallback
}
源码链接:https://github.com/golang/go/blob/master/src/net/http/sniff.go#L21