README.md
1# filetype [![Build Status](https://travis-ci.org/h2non/filetype.svg)](https://travis-ci.org/h2non/filetype) [![GoDoc](https://godoc.org/github.com/h2non/filetype?status.svg)](https://godoc.org/github.com/h2non/filetype) [![Go Report Card](http://goreportcard.com/badge/h2non/filetype)](http://goreportcard.com/report/h2non/filetype) [![Go Version](https://img.shields.io/badge/go-v1.0+-green.svg?style=flat)](https://github.com/h2non/gentleman)
2
3Small and dependency free [Go](https://golang.org) package to infer file and MIME type checking the [magic numbers](<https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files>) signature.
4
5For SVG file type checking, see [go-is-svg](https://github.com/h2non/go-is-svg) package. Python port: [filetype.py](https://github.com/h2non/filetype.py).
6
7## Features
8
9- Supports a [wide range](#supported-types) of file types
10- Provides file extension and proper MIME type
11- File discovery by extension or MIME type
12- File discovery by class (image, video, audio...)
13- Provides a bunch of helpers and file matching shortcuts
14- [Pluggable](#add-additional-file-type-matchers): add custom new types and matchers
15- Simple and semantic API
16- [Blazing fast](#benchmarks), even processing large files
17- Only first 262 bytes representing the max file header is required, so you can just [pass a slice](#file-header)
18- Dependency free (just Go code, no C compilation needed)
19- Cross-platform file recognition
20
21## Installation
22
23```bash
24go get github.com/h2non/filetype
25```
26
27## API
28
29See [Godoc](https://godoc.org/github.com/h2non/filetype) reference.
30
31### Subpackages
32
33- [`github.com/h2non/filetype/types`](https://godoc.org/github.com/h2non/filetype/types)
34- [`github.com/h2non/filetype/matchers`](https://godoc.org/github.com/h2non/filetype/matchers)
35
36## Examples
37
38#### Simple file type checking
39
40```go
41package main
42
43import (
44 "fmt"
45 "io/ioutil"
46
47 "github.com/h2non/filetype"
48)
49
50func main() {
51 buf, _ := ioutil.ReadFile("sample.jpg")
52
53 kind, _ := filetype.Match(buf)
54 if kind == filetype.Unknown {
55 fmt.Println("Unknown file type")
56 return
57 }
58
59 fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
60}
61```
62
63#### Check type class
64
65```go
66package main
67
68import (
69 "fmt"
70 "io/ioutil"
71
72 "github.com/h2non/filetype"
73)
74
75func main() {
76 buf, _ := ioutil.ReadFile("sample.jpg")
77
78 if filetype.IsImage(buf) {
79 fmt.Println("File is an image")
80 } else {
81 fmt.Println("Not an image")
82 }
83}
84```
85
86#### Supported type
87
88```go
89package main
90
91import (
92 "fmt"
93
94 "github.com/h2non/filetype"
95)
96
97func main() {
98 // Check if file is supported by extension
99 if filetype.IsSupported("jpg") {
100 fmt.Println("Extension supported")
101 } else {
102 fmt.Println("Extension not supported")
103 }
104
105 // Check if file is supported by extension
106 if filetype.IsMIMESupported("image/jpeg") {
107 fmt.Println("MIME type supported")
108 } else {
109 fmt.Println("MIME type not supported")
110 }
111}
112```
113
114#### File header
115
116```go
117package main
118
119import (
120 "fmt"
121 "io/ioutil"
122
123 "github.com/h2non/filetype"
124)
125
126func main() {
127 // Open a file descriptor
128 file, _ := os.Open("movie.mp4")
129
130 // We only have to pass the file header = first 261 bytes
131 head := make([]byte, 261)
132 file.Read(head)
133
134 if filetype.IsImage(head) {
135 fmt.Println("File is an image")
136 } else {
137 fmt.Println("Not an image")
138 }
139}
140```
141
142#### Add additional file type matchers
143
144```go
145package main
146
147import (
148 "fmt"
149
150 "github.com/h2non/filetype"
151)
152
153var fooType = filetype.NewType("foo", "foo/foo")
154
155func fooMatcher(buf []byte) bool {
156 return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02
157}
158
159func main() {
160 // Register the new matcher and its type
161 filetype.AddMatcher(fooType, fooMatcher)
162
163 // Check if the new type is supported by extension
164 if filetype.IsSupported("foo") {
165 fmt.Println("New supported type: foo")
166 }
167
168 // Check if the new type is supported by MIME
169 if filetype.IsMIMESupported("foo/foo") {
170 fmt.Println("New supported MIME type: foo/foo")
171 }
172
173 // Try to match the file
174 fooFile := []byte{0x01, 0x02}
175 kind, _ := filetype.Match(fooFile)
176 if kind == filetype.Unknown {
177 fmt.Println("Unknown file type")
178 } else {
179 fmt.Printf("File type matched: %s\n", kind.Extension)
180 }
181}
182```
183
184## Supported types
185
186#### Image
187
188- **jpg** - `image/jpeg`
189- **png** - `image/png`
190- **gif** - `image/gif`
191- **webp** - `image/webp`
192- **cr2** - `image/x-canon-cr2`
193- **tif** - `image/tiff`
194- **bmp** - `image/bmp`
195- **heif** - `image/heif`
196- **jxr** - `image/vnd.ms-photo`
197- **psd** - `image/vnd.adobe.photoshop`
198- **ico** - `image/vnd.microsoft.icon`
199- **dwg** - `image/vnd.dwg`
200
201#### Video
202
203- **mp4** - `video/mp4`
204- **m4v** - `video/x-m4v`
205- **mkv** - `video/x-matroska`
206- **webm** - `video/webm`
207- **mov** - `video/quicktime`
208- **avi** - `video/x-msvideo`
209- **wmv** - `video/x-ms-wmv`
210- **mpg** - `video/mpeg`
211- **flv** - `video/x-flv`
212- **3gp** - `video/3gpp`
213
214#### Audio
215
216- **mid** - `audio/midi`
217- **mp3** - `audio/mpeg`
218- **m4a** - `audio/m4a`
219- **ogg** - `audio/ogg`
220- **flac** - `audio/x-flac`
221- **wav** - `audio/x-wav`
222- **amr** - `audio/amr`
223- **aac** - `audio/aac`
224
225#### Archive
226
227- **epub** - `application/epub+zip`
228- **zip** - `application/zip`
229- **tar** - `application/x-tar`
230- **rar** - `application/vnd.rar`
231- **gz** - `application/gzip`
232- **bz2** - `application/x-bzip2`
233- **7z** - `application/x-7z-compressed`
234- **xz** - `application/x-xz`
235- **pdf** - `application/pdf`
236- **exe** - `application/vnd.microsoft.portable-executable`
237- **swf** - `application/x-shockwave-flash`
238- **rtf** - `application/rtf`
239- **iso** - `application/x-iso9660-image`
240- **eot** - `application/octet-stream`
241- **ps** - `application/postscript`
242- **sqlite** - `application/vnd.sqlite3`
243- **nes** - `application/x-nintendo-nes-rom`
244- **crx** - `application/x-google-chrome-extension`
245- **cab** - `application/vnd.ms-cab-compressed`
246- **deb** - `application/vnd.debian.binary-package`
247- **ar** - `application/x-unix-archive`
248- **Z** - `application/x-compress`
249- **lz** - `application/x-lzip`
250- **rpm** - `application/x-rpm`
251- **elf** - `application/x-executable`
252- **dcm** - `application/dicom`
253
254#### Documents
255
256- **doc** - `application/msword`
257- **docx** - `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
258- **xls** - `application/vnd.ms-excel`
259- **xlsx** - `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
260- **ppt** - `application/vnd.ms-powerpoint`
261- **pptx** - `application/vnd.openxmlformats-officedocument.presentationml.presentation`
262
263#### Font
264
265- **woff** - `application/font-woff`
266- **woff2** - `application/font-woff`
267- **ttf** - `application/font-sfnt`
268- **otf** - `application/font-sfnt`
269
270#### Application
271
272- **wasm** - `application/wasm`
273- **dex** - `application/vnd.android.dex`
274- **dey** - `application/vnd.android.dey`
275
276## Benchmarks
277
278Measured using [real files](https://github.com/h2non/filetype/tree/master/fixtures).
279
280Environment: OSX x64 i7 2.7 Ghz
281
282```bash
283BenchmarkMatchTar-8 1000000 1083 ns/op
284BenchmarkMatchZip-8 1000000 1162 ns/op
285BenchmarkMatchJpeg-8 1000000 1280 ns/op
286BenchmarkMatchGif-8 1000000 1315 ns/op
287BenchmarkMatchPng-8 1000000 1121 ns/op
288```
289
290## License
291
292MIT - Tomas Aparicio
293