golang通过魔数签名检测文件类型的插件库filetype的使用

Golang通过魔数签名检测文件类型的插件库filetype的使用

filetype是一个小型且无依赖的Go包,用于通过检查魔数签名来推断文件和MIME类型。

特性

  • 支持广泛的文件类型
  • 提供文件扩展名和正确的MIME类型
  • 通过扩展名或MIME类型发现文件
  • 通过类别(图像、视频、音频等)发现文件
  • 提供大量帮助程序和文件匹配快捷方式
  • 可插拔:添加自定义新类型和匹配器
  • 简单语义化的API
  • 处理大文件时速度极快
  • 只需要前262字节(最大文件头),所以可以只传递一个切片
  • 无依赖(纯Go代码,无需C编译)
  • 跨平台文件识别

安装

go get github.com/h2non/filetype

使用示例

简单文件类型检查

package main

import (
  "fmt"
  "io/ioutil"

  "github.com/h2non/filetype"
)

func main() {
  buf, _ := ioutil.ReadFile("sample.jpg")

  kind, _ := filetype.Match(buf)
  if kind == filetype.Unknown {
    fmt.Println("Unknown file type")
    return
  }

  fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
}

检查类型类别

package main

import (
  "fmt"
  "io/ioutil"

  "github.com/h2non/filetype"
)

func main() {
  buf, _ := ioutil.ReadFile("sample.jpg")

  if filetype.IsImage(buf) {
    fmt.Println("File is an image")
  } else {
    fmt.Println("Not an image")
  }
}

检查支持的类型

package main

import (
  "fmt"

  "github.com/h2non/filetype"
)

func main() {
  // 通过扩展名检查文件是否支持
  if filetype.IsSupported("jpg") {
    fmt.Println("Extension supported")
  } else {
    fmt.Println("Extension not supported")
  }

  // 通过MIME类型检查文件是否支持
  if filetype.IsMIMESupported("image/jpeg") {
    fmt.Println("MIME type supported")
  } else {
    fmt.Println("MIME type not supported")
  }
}

文件头检查

package main

import (
  "fmt"
  "os"

  "github.com/h2non/filetype"
)

func main() {
  // 打开文件描述符
  file, _ := os.Open("movie.mp4")

  // 只需要传递文件头 = 前261字节
  head := make([]byte, 261)
  file.Read(head)

  if filetype.IsImage(head) {
    fmt.Println("File is an image")
  } else {
    fmt.Println("Not an image")
  }
}

添加自定义文件类型匹配器

package main

import (
  "fmt"

  "github.com/h2non/filetype"
)

var fooType = filetype.NewType("foo", "foo/foo")

func fooMatcher(buf []byte) bool {
  return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02
}

func main() {
  // 注册新的匹配器和类型
  filetype.AddMatcher(fooType, fooMatcher)

  // 检查新类型是否通过扩展名支持
  if filetype.IsSupported("foo") {
    fmt.Println("New supported type: foo")
  }

  // 检查新类型是否通过MIME支持
  if filetype.IsMIMESupported("foo/foo") {
    fmt.Println("New supported MIME type: foo/foo")
  }

  // 尝试匹配文件
  fooFile := []byte{0x01, 0x02}
  kind, _ := filetype.Match(fooFile)
  if kind == filetype.Unknown {
    fmt.Println("Unknown file type")
  } else {
    fmt.Printf("File type matched: %s\n", kind.Extension)
  }
}

支持的文件类型

图像

  • jpg - image/jpeg
  • png - image/png
  • gif - image/gif
  • webp - image/webp
  • cr2 - image/x-canon-cr2
  • tif - image/tiff
  • bmp - image/bmp
  • heif - image/heif
  • jxr - image/vnd.ms-photo
  • psd - image/vnd.adobe.photoshop
  • ico - image/vnd.microsoft.icon
  • dwg - image/vnd.dwg
  • avif - image/avif

视频

  • mp4 - video/mp4
  • m4v - video/x-m4v
  • mkv - video/x-matroska
  • webm - video/webm
  • mov - video/quicktime
  • avi - video/x-msvideo
  • wmv - video/x-ms-wmv
  • mpg - video/mpeg
  • flv - video/x-flv
  • 3gp - video/3gpp

音频

  • mid - audio/midi
  • mp3 - audio/mpeg
  • m4a - audio/mp4
  • ogg - audio/ogg
  • flac - audio/x-flac
  • wav - audio/x-wav
  • amr - audio/amr
  • aac - audio/aac
  • aiff - audio/x-aiff

归档

  • epub - application/epub+zip
  • zip - application/zip
  • tar - application/x-tar
  • rar - application/vnd.rar
  • gz - application/gzip
  • bz2 - application/x-bzip2
  • 7z - application/x-7z-compressed
  • xz - application/x-xz
  • zstd - application/zstd
  • pdf - application/pdf
  • exe - application/vnd.microsoft.portable-executable
  • swf - application/x-shockwave-flash
  • rtf - application/rtf
  • iso - application/x-iso9660-image
  • eot - application/octet-stream
  • ps - application/postscript
  • sqlite - application/vnd.sqlite3
  • nes - application/x-nintendo-nes-rom
  • crx - application/x-google-chrome-extension
  • cab - application/vnd.ms-cab-compressed
  • deb - application/vnd.debian.binary-package
  • ar - application/x-unix-archive
  • Z - application/x-compress
  • lz - application/x-lzip
  • rpm - application/x-rpm
  • elf - application/x-executable
  • dcm - application/dicom

文档

  • doc - application/msword
  • docx - application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • xls - application/vnd.ms-excel
  • xlsx - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • ppt - application/vnd.ms-powerpoint
  • pptx - application/vnd.openxmlformats-officedocument.presentationml.presentation

字体

  • woff - application/font-woff
  • woff2 - application/font-woff
  • ttf - application/font-sfnt
  • otf - application/font-sfnt

应用程序

  • wasm - application/wasm
  • dex - application/vnd.android.dex
  • dey - application/vnd.android.dey
  • parquet - application/vnd.apache.parquet

更多关于golang通过魔数签名检测文件类型的插件库filetype的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang通过魔数签名检测文件类型的插件库filetype的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang文件类型检测库filetype使用指南

filetype是一个基于魔数(magic number)签名的Golang文件类型检测库,它可以快速准确地识别文件类型而不仅仅依赖文件扩展名。

安装

go get github.com/h2non/filetype

基本使用

1. 检测已知文件类型

package main

import (
	"fmt"
	"io/ioutil"
	
	"github.com/h2non/filetype"
)

func main() {
	// 读取文件内容
	buf, _ := ioutil.ReadFile("sample.jpg")
	
	// 检测文件类型
	kind, _ := filetype.Match(buf)
	if kind == filetype.Unknown {
		fmt.Println("Unknown file type")
		return
	}
	
	fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
}

2. 检查特定文件类型

// 检查是否是JPEG图片
if filetype.IsImage(buf) {
	fmt.Println("File is an image")
}

// 更精确的检查
if filetype.Is(buf, "jpg") {
	fmt.Println("File is a JPEG image")
}

// 检查MIME类型
if filetype.IsMIME(buf, "image/jpeg") {
	fmt.Println("File is a JPEG image")
}

高级功能

1. 自定义类型检测

package main

import (
	"fmt"
	
	"github.com/h2non/filetype"
	"github.com/h2non/filetype/types"
)

// 定义自定义文件类型
var FooType = types.Type{
	Extension: "foo",
	MIME:      types.MIME{Type: "application", Value: "foo"},
}

// 自定义匹配函数
func fooMatcher(buf []byte) bool {
	return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02
}

func main() {
	// 注册自定义类型
	filetype.AddMatcher(FooType, fooMatcher)
	
	// 现在可以检测自定义类型了
	buf := []byte{0x01, 0x02}
	kind, _ := filetype.Match(buf)
	if kind == FooType {
		fmt.Println("File is a foo file")
	}
}

2. 从Reader检测

package main

import (
	"fmt"
	"os"
	
	"github.com/h2non/filetype"
)

func main() {
	file, _ := os.Open("sample.png")
	defer file.Close()
	
	// 从reader检测
	head := make([]byte, 261) // 需要足够大的缓冲区
	file.Read(head)
	
	kind, _ := filetype.Match(head)
	fmt.Printf("File type: %s\n", kind.Extension)
}

3. 文件类型分类检查

buf, _ := ioutil.ReadFile("sample.pdf")

if filetype.IsArchive(buf) {
	fmt.Println("File is an archive")
} else if filetype.IsAudio(buf) {
	fmt.Println("File is an audio")
} else if filetype.IsDocument(buf) {
	fmt.Println("File is a document")
} else if filetype.IsFont(buf) {
	fmt.Println("File is a font")
} else if filetype.IsImage(buf) {
	fmt.Println("File is an image")
} else if filetype.IsVideo(buf) {
	fmt.Println("File is a video")
}

性能优化

对于大文件,不需要读取整个文件,只需要读取文件头部即可:

func readFileHeader(filePath string) ([]byte, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	
	// 只需要前261字节即可识别大多数文件类型
	head := make([]byte, 261)
	_, err = file.Read(head)
	if err != nil {
		return nil, err
	}
	
	return head, nil
}

支持的格式

filetype支持检测多种常见格式,包括但不限于:

  • 图片: jpg, png, gif, webp, bmp, ico等
  • 视频: mp4, webm, mkv, mov, avi等
  • 音频: mp3, flac, ogg, wav, amr等
  • 文档: pdf, docx, pptx, xlsx等
  • 压缩文件: zip, tar, rar, gz, bz2等
  • 字体: ttf, woff, woff2等

总结

filetype是一个功能强大且易于使用的文件类型检测库,它通过分析文件内容的魔数签名来准确识别文件类型,比依赖文件扩展名更可靠。它支持扩展自定义类型检测,并针对性能进行了优化,适合在生产环境中使用。

回到顶部