Skip to content

Commit

Permalink
Add more docs and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriel-vasile committed Dec 10, 2019
1 parent d686b1b commit 69083ea
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 32 deletions.
60 changes: 60 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Examples
[Detect MIME type](#detect)
[Check against MIME type](#check)
[Check base MIME type](#check-parent)

### Detect
Get the MIME type from a slice of bytes, from a reader and from a file.
```go
file := "testdata/pdf.pdf"
reader, _ := os.Open(file)
data, _ := ioutil.ReadFile(file)

// Detecting the same data three times, for the sake of example.
dmime := mimetype.Detect(data)
rmime, rerr := mimetype.DetectReader(reader)
fmime, ferr := mimetype.DetectFile(file)

fmt.Println(dmime, rmime, fmime)
fmt.Println(rerr, ferr)

// Output: application/pdf application/pdf application/pdf
// <nil> <nil>
```

### Check
Test if some file has a specific MIME type. Also accepts MIME type aliases.
```go
mime, err := mimetype.DetectFile("testdata/zip.zip")
// application/x-zip is an alias of application/zip,
// therefore Is returns true both times.
fmt.Println(mime.Is("application/zip"), mime.Is("application/x-zip"), err)

// Output: true true <nil>
```

### Check parent
Test if some file has a specific base MIME type. First perform a detect on the input, then navigate parents until the base MIME type if found.
```go
// Ex: if you are interested in text/plain and all of its subtypes:
// text/html, text/xml, text/csv, etc.
mime, err := mimetype.DetectFile("testdata/html.html")

isText := false
for ; mime != nil; mime = mime.Parent() {
if mime.Is("text/plain") {
isText = true
}
}

// isText is true, even if the detected MIME was text/html.
fmt.Println(isText, err)

// Output: true <nil>
```
When calling `DetectReader` on a `ReadSeeker` interface, such as `os.File`, make sure
to reset the offset of the reader to the beginning if needed:
```go
_, err = file.Seek(0, io.SeekStart)
```

39 changes: 13 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,17 @@
go get github.com/gabriel-vasile/mimetype
```

## Use
See [GoDoc](https://godoc.org/github.com/gabriel-vasile/mimetype) for full reference.
The library exposes three functions you can use in order to find a file type.
```go
func Detect(in []byte) (mime, extension string){}
func DetectReader(r io.Reader) (mime, extension string, err error){}
func DetectFile(file string) (mime, extension string, err error){}
```

If you need to check input against a certain list of MIME types, use `Matches`:
```go
func Matches(in []byte, expectedMimes ...string) (match bool, err error){}
func MatchesReader(r io.Reader, expectedMimes ...string) (match bool, err error){}
func MatchesFile(file string, expectedMimes ...string) (match bool, err error){}
```
Unlike `Detect`, which returns a single MIME type, `Matches` searches against all
the aliases of the MIME type detected from the input. For example, provided `in` is a
zip archive, both `Matches(in, "application/zip")` and `Matches(in, "application/x-zip-compressed")`
will return a positive result.
## Usage
There is quick [examples](EXAMPLES.md) and
[GoDoc](https://godoc.org/github.com/gabriel-vasile/mimetype) for full reference.

When detecting from a `ReadSeeker` interface, such as `os.File`, make sure
to reset the offset of the reader to the beginning if needed:
```go
_, err = file.Seek(0, io.SeekStart)
```
## Upgrade from v0.3.x to v1.x
In v1.x the detect functions no longer return the MIME type and extension as
strings. Instead they return a [MIME](https://godoc.org/github.com/gabriel-vasile/mimetype#MIME)
struct. To get the string value of the MIME and the extension, call the
`String()` and the `Extension()` methods.
In order to play better with the stdlib `mime` package, v1.x extensions
include the leading dot, as in ".html".

## Supported MIME types
See [supported mimes](supported_mimes.md) for the list of detected MIME types.
Expand All @@ -66,9 +52,10 @@ If support is needed for a specific file format, please open an [issue](https://
**mimetype** uses an hierarchical structure to keep the MIME type detection logic.
This reduces the number of calls needed for detecting the file type. The reason
behind this choice is that there are file formats used as containers for other
file formats. For example, Microsoft office files are just zip archives,
file formats. For example, Microsoft Office files are just zip archives,
containing specific metadata files. Once a file a file has been identified as a
zip, there is no need to check if it is a text file.
zip, there is no need to check if it is a text file, but it is worth checking if
it is an Microsoft Office file.
<div align="center">
<img alt="structure" src="mimetype.gif" width="88%">
</div>
Expand Down
15 changes: 9 additions & 6 deletions example_mimetype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func Example_detect() {
dmime := mimetype.Detect(data)
rmime, rerr := mimetype.DetectReader(reader)
fmime, ferr := mimetype.DetectFile(file)

fmt.Println(dmime, rmime, fmime)
fmt.Println(rerr, ferr)

Expand All @@ -25,7 +26,8 @@ func Example_detect() {
}

// To check if some bytes/reader/file has a specific MIME type, first perform
// a detect on the input and then test against the MIME.
// a detect on the input and then test against the MIME. `Is` also works with
// MIME aliases.
func Example_check() {
mime, err := mimetype.DetectFile("testdata/zip.zip")
// application/x-zip is an alias of application/zip,
Expand All @@ -39,8 +41,8 @@ func Example_check() {
// a detect on the input and then navigate the parents until the base MIME type
// is found.
func Example_parent() {
// text/html is a subclass of text/plain.
// mime is text/html.
// Ex: if you are interested in text/plain and all of its subtypes:
// text/html, text/xml, text/csv, etc.
mime, err := mimetype.DetectFile("testdata/html.html")

isText := false
Expand All @@ -50,6 +52,7 @@ func Example_parent() {
}
}

// isText is true, even if the detected MIME was text/html.
fmt.Println(isText, err)

// Output: true <nil>
Expand All @@ -59,7 +62,7 @@ func ExampleDetect() {
data, err := ioutil.ReadFile("testdata/zip.zip")
mime := mimetype.Detect(data)

fmt.Println(mime.String(), err)
fmt.Println(mime, err)

// Output: application/zip <nil>
}
Expand All @@ -68,15 +71,15 @@ func ExampleDetectReader() {
data, oerr := os.Open("testdata/zip.zip")
mime, merr := mimetype.DetectReader(data)

fmt.Println(mime.String(), oerr, merr)
fmt.Println(mime, oerr, merr)

// Output: application/zip <nil> <nil>
}

func ExampleDetectFile() {
mime, err := mimetype.DetectFile("testdata/zip.zip")

fmt.Println(mime.String(), err)
fmt.Println(mime, err)

// Output: application/zip <nil>
}
Expand Down
5 changes: 5 additions & 0 deletions mimetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
)

// Detect returns the MIME type found from the provided byte slice.
//
// Failure to identify the format results in application/octet-stream
// being returned.
func Detect(in []byte) (mime *MIME) {
Expand All @@ -26,8 +27,10 @@ func Detect(in []byte) (mime *MIME) {
}

// DetectReader returns the MIME type of the provided reader.
//
// The result is always a valid MIME type, with application/octet-stream
// returned when identification failed with or without an error.
// Any error returned is related to the reading from the input reader.
func DetectReader(r io.Reader) (mime *MIME, err error) {
in := make([]byte, matchers.ReadLimit)
n, err := r.Read(in)
Expand All @@ -40,8 +43,10 @@ func DetectReader(r io.Reader) (mime *MIME, err error) {
}

// DetectFile returns the MIME type of the provided file.
//
// The result is always a valid MIME type, with application/octet-stream
// returned when identification failed with or without an error.
// Any error returned is related to the opening and reading from the input file.
func DetectFile(file string) (mime *MIME, err error) {
f, err := os.Open(file)
if err != nil {
Expand Down

0 comments on commit 69083ea

Please sign in to comment.