mimetype – github.com/gabriel-vasile/mimetype Index | Examples | Files | Directories

package mimetype

import "github.com/gabriel-vasile/mimetype"

Package mimetype uses magic number signatures to detect the MIME type of a file.

Example (Detect)

Code:play 

package main

import (
	"bytes"
	"fmt"
	"os"

	"github.com/gabriel-vasile/mimetype"
)

func main() {
	testBytes := []byte("This random text should have a MIME type of text/plain; charset=utf-8.")

	mime := mimetype.Detect(testBytes)
	fmt.Println(mime.Is("text/plain"), mime.String(), mime.Extension())

	mime, err := mimetype.DetectReader(bytes.NewReader(testBytes))
	fmt.Println(mime.Is("text/plain"), mime.String(), mime.Extension(), err)

	mime, err = mimetype.DetectFile("a nonexistent file")
	fmt.Println(mime.Is("application/octet-stream"), mime.String(), os.IsNotExist(err))
}

Output:

true text/plain; charset=utf-8 .txt
true text/plain; charset=utf-8 .txt <nil>
true application/octet-stream true
Example (ReusableReader)

When detecting from an io.Reader, mimetype will read the header of the input. This means the reader cannot just be reused (to save the file, for example) because the header is now missing from the reader.

If the input is a pure io.Reader, use io.TeeReader, io.MultiReader and bytes.Buffer to create a new reader containing the whole unaltered data.

If the input is an io.ReadSeeker, call reader.Seek(0, io.SeekStart) to rewind it.

Code:play 

package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/gabriel-vasile/mimetype"
)

func main() {
	// Set header size to 10 bytes for this example.
	mimetype.SetLimit(10)

	testBytes := []byte("This random text should have a MIME type of text/plain; charset=utf-8.")
	inputReader := bytes.NewReader(testBytes)

	// buf will store the 10 bytes mimetype used for detection.
	header := bytes.NewBuffer(nil)

	// After DetectReader, the first 10 bytes are stored in buf.
	mime, err := mimetype.DetectReader(io.TeeReader(inputReader, header))

	// Concatenate back the first 10 bytes.
	// reusableReader now contains the complete, original data.
	reusableReader := io.MultiReader(header, inputReader)
	text, _ := ioutil.ReadAll(reusableReader)
	fmt.Println(mime, bytes.Equal(testBytes, text), err)
}

Output:

text/plain; charset=utf-8 true <nil>
Example (TextVsBinary)

Considering the definition of a binary file as "a computer file that is not a text file", they can differentiated by searching for the text/plain MIME in their MIME hierarchy.

Code:play 

package main

import (
	"fmt"

	"github.com/gabriel-vasile/mimetype"
)

func main() {
	testBytes := []byte("This random text should have a MIME type of text/plain; charset=utf-8.")
	detectedMIME := mimetype.Detect(testBytes)

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

	fmt.Println(isBinary, detectedMIME)
}

Output:

false text/plain; charset=utf-8
Example (Whitelist)

Code:play 

package main

import (
	"fmt"

	"github.com/gabriel-vasile/mimetype"
)

func main() {
	testBytes := []byte("This random text should have a MIME type of text/plain; charset=utf-8.")
	allowed := []string{"text/plain", "application/zip", "application/pdf"}
	mime := mimetype.Detect(testBytes)

	if mimetype.EqualsAny(mime.String(), allowed...) {
		fmt.Printf("%s is allowed\n", mime)
	} else {
		fmt.Printf("%s is now allowed\n", mime)
	}
}

Output:

text/plain; charset=utf-8 is allowed

Index

Examples

Functions

func EqualsAny

func EqualsAny(s string, mimes ...string) bool

EqualsAny reports whether s MIME type is equal to any MIME type in mimes. MIME type equality test is done on the "type/subtype" section, ignores any optional MIME parameters, ignores any leading and trailing whitespace, and is case insensitive.

func SetLimit

func SetLimit(limit uint32)

SetLimit sets the maximum number of bytes read from input when detecting the MIME type. Increasing the limit provides better detection for file formats which store their magical numbers towards the end of the file: docx, pptx, xlsx, etc. A limit of 0 means the whole input file will be used.

Types

type MIME

type MIME struct {
	// contains filtered or unexported fields
}

MIME struct holds information about a file format: the string representation of the MIME type, the extension and the parent file format.

func Detect

func Detect(in []byte) *MIME

Detect returns the MIME type found from the provided byte slice.

The result is always a valid MIME type, with application/octet-stream returned when identification failed.

func DetectFile

func DetectFile(file string) (*MIME, 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 DetectReader

func DetectReader(r io.Reader) (*MIME, error)

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.

DetectReader assumes the reader offset is at the start. If the input is an io.ReadSeeker you previously read from, it should be rewinded before detection:

reader.Seek(0, io.SeekStart)

func (*MIME) Extension

func (m *MIME) Extension() string

Extension returns the file extension associated with the MIME type. It includes the leading dot, as in ".html". When the file format does not have an extension, the empty string is returned.

func (*MIME) Is

func (m *MIME) Is(expectedMIME string) bool

Is checks whether this MIME type, or any of its aliases, is equal to the expected MIME type. MIME type equality test is done on the "type/subtype" section, ignores any optional MIME parameters, ignores any leading and trailing whitespace, and is case insensitive.

func (*MIME) Parent

func (m *MIME) Parent() *MIME

Parent returns the parent MIME type from the hierarchy. Each MIME type has a non-nil parent, except for the root MIME type.

For example, the application/json and text/html MIME types have text/plain as their parent because they are text files who happen to contain JSON or HTML. Another example is the ZIP format, which is used as container for Microsoft Office files, EPUB files, JAR files, and others.

func (*MIME) String

func (m *MIME) String() string

String returns the string representation of the MIME type, e.g., "application/zip".

Source Files

mime.go mimetype.go tree.go

Directories

PathSynopsis
internal
Version
v1.2.0
Published
Mar 1, 2021
Platform
windows/amd64
Imports
6 packages
Last checked
5 minutes ago

Tools for package owners.