1# filetype [![Build Status](https://travis-ci.org/h2non/filetype.png)](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.
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 261 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 gopkg.in/h2non/filetype.v1
25```
26
27## API
28
29See [Godoc](https://godoc.org/github.com/h2non/filetype) reference.
30
31### Subpackages
32
33- [`gopkg.in/h2non/filetype.v1/types`](https://godoc.org/github.com/h2non/filetype/types)
34- [`gopkg.in/h2non/filetype.v1/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  "gopkg.in/h2non/filetype.v1"
46  "io/ioutil"
47)
48
49func main() {
50  buf, _ := ioutil.ReadFile("sample.jpg")
51
52  kind, unkwown := filetype.Match(buf)
53  if unkwown != nil {
54    fmt.Printf("Unkwown: %s", unkwown)
55    return
56  }
57
58  fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
59}
60```
61
62#### Check type class
63
64```go
65package main
66
67import (
68  "fmt"
69  "gopkg.in/h2non/filetype.v1"
70  "io/ioutil"
71)
72
73func main() {
74  buf, _ := ioutil.ReadFile("sample.jpg")
75
76  if filetype.IsImage(buf) {
77    fmt.Println("File is an image")
78  } else {
79    fmt.Println("Not an image")
80  }
81}
82```
83
84#### Supported type
85
86```go
87package main
88
89import (
90  "fmt"
91  "gopkg.in/h2non/filetype.v1"
92)
93
94func main() {
95  // Check if file is supported by extension
96  if filetype.IsSupported("jpg") {
97    fmt.Println("Extension supported")
98  } else {
99    fmt.Println("Extension not supported")
100  }
101
102  // Check if file is supported by extension
103  if filetype.IsMIMESupported("image/jpeg") {
104    fmt.Println("MIME type supported")
105  } else {
106    fmt.Println("MIME type not supported")
107  }
108}
109```
110
111#### File header
112
113```go
114package main
115
116import (
117  "fmt"
118  "gopkg.in/h2non/filetype.v1"
119  "io/ioutil"
120)
121
122func main() {
123  // Read a file
124  buf, _ := ioutil.ReadFile("sample.jpg")
125
126  // We only have to pass the file header = first 261 bytes
127  head := buf[:261]
128
129  if filetype.IsImage(head) {
130    fmt.Println("File is an image")
131  } else {
132    fmt.Println("Not an image")
133  }
134}
135```
136
137#### Add additional file type matchers
138
139```go
140package main
141
142import (
143  "fmt"
144  "gopkg.in/h2non/filetype.v1"
145)
146
147var fooType = filetype.NewType("foo", "foo/foo")
148
149func fooMatcher(buf []byte) bool {
150  return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02
151}
152
153func main() {
154  // Register the new matcher and its type
155  filetype.AddMatcher(fooType, fooMatcher)
156
157  // Check if the new type is supported by extension
158  if filetype.IsSupported("foo") {
159    fmt.Println("New supported type: foo")
160  }
161
162  // Check if the new type is supported by MIME
163  if filetype.IsMIMESupported("foo/foo") {
164    fmt.Println("New supported MIME type: foo/foo")
165  }
166
167  // Try to match the file
168  fooFile := []byte{0x01, 0x02}
169  kind, _ := filetype.Match(fooFile)
170  if kind == filetype.Unknown {
171    fmt.Println("Unknown file type")
172  } else {
173    fmt.Printf("File type matched: %s\n", kind.Extension)
174  }
175}
176```
177
178## Supported types
179
180#### Image
181
182- **jpg** - `image/jpeg`
183- **png** - `image/png`
184- **gif** - `image/gif`
185- **webp** - `image/webp`
186- **cr2** - `image/x-canon-cr2`
187- **tif** - `image/tiff`
188- **bmp** - `image/bmp`
189- **jxr** - `image/vnd.ms-photo`
190- **psd** - `image/vnd.adobe.photoshop`
191- **ico** - `image/x-icon`
192
193#### Video
194
195- **mp4** - `video/mp4`
196- **m4v** - `video/x-m4v`
197- **mkv** - `video/x-matroska`
198- **webm** - `video/webm`
199- **mov** - `video/quicktime`
200- **avi** - `video/x-msvideo`
201- **wmv** - `video/x-ms-wmv`
202- **mpg** - `video/mpeg`
203- **flv** - `video/x-flv`
204
205#### Audio
206
207- **mid** - `audio/midi`
208- **mp3** - `audio/mpeg`
209- **m4a** - `audio/m4a`
210- **ogg** - `audio/ogg`
211- **flac** - `audio/x-flac`
212- **wav** - `audio/x-wav`
213- **amr** - `audio/amr`
214
215#### Archive
216
217- **epub** - `application/epub+zip`
218- **zip** - `application/zip`
219- **tar** - `application/x-tar`
220- **rar** - `application/x-rar-compressed`
221- **gz** - `application/gzip`
222- **bz2** - `application/x-bzip2`
223- **7z** - `application/x-7z-compressed`
224- **xz** - `application/x-xz`
225- **pdf** - `application/pdf`
226- **exe** - `application/x-msdownload`
227- **swf** - `application/x-shockwave-flash`
228- **rtf** - `application/rtf`
229- **eot** - `application/octet-stream`
230- **ps** - `application/postscript`
231- **sqlite** - `application/x-sqlite3`
232- **nes** - `application/x-nintendo-nes-rom`
233- **crx** - `application/x-google-chrome-extension`
234- **cab** - `application/vnd.ms-cab-compressed`
235- **deb** - `application/x-deb`
236- **ar** - `application/x-unix-archive`
237- **Z** - `application/x-compress`
238- **lz** - `application/x-lzip`
239- **rpm** - `application/x-rpm`
240- **elf** - `application/x-executable`
241
242#### Font
243
244- **woff** - `application/font-woff`
245- **woff2** - `application/font-woff`
246- **ttf** - `application/font-sfnt`
247- **otf** - `application/font-sfnt`
248
249## Benchmarks
250
251Measured using [real files](https://github.com/h2non/filetype/tree/master/fixtures).
252
253Environment: OSX x64 i7 2.7 Ghz
254
255```bash
256BenchmarkMatchTar-8    1000000        1083 ns/op
257BenchmarkMatchZip-8    1000000        1162 ns/op
258BenchmarkMatchJpeg-8   1000000        1280 ns/op
259BenchmarkMatchGif-8    1000000        1315 ns/op
260BenchmarkMatchPng-8    1000000        1121 ns/op
261```
262
263## License
264
265MIT - Tomas Aparicio
266