github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/filetype/filetype.go (about)

     1  package filetype
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"mime"
     7  	"strings"
     8  
     9  	"github.com/cozy/cozy-stack/pkg/consts"
    10  	ftype "github.com/h2non/filetype"
    11  )
    12  
    13  // DefaultType is the type used when we can't know/guess the filetype.
    14  const DefaultType = "application/octet-stream"
    15  
    16  // ByExtension calls mime.TypeByExtension, and removes optional parameters, to
    17  // keep only the type and subtype.
    18  // Example: text/html
    19  func ByExtension(ext string) string {
    20  	switch ext {
    21  	case ".cozy-note":
    22  		return consts.NoteMimeType
    23  	case ".url":
    24  		return consts.ShortcutMimeType
    25  	}
    26  	mimeParts := strings.SplitN(mime.TypeByExtension(ext), ";", 2)
    27  	return strings.TrimSpace(mimeParts[0])
    28  }
    29  
    30  // Match returns the mime-type (no charset) if it can guess from the first
    31  // bytes, or the default content-type else.
    32  func Match(buf []byte) string {
    33  	mimetype := DefaultType
    34  	if kind, err := ftype.Match(buf); err == nil {
    35  		mimetype = kind.MIME.Value
    36  	}
    37  	return mimetype
    38  }
    39  
    40  // FromReader takes a reader, sniffs the beginning of it, and returns the
    41  // mime-type (no charset) and a new reader that's the concatenation of the
    42  // bytes sniffed and the remaining reader.
    43  func FromReader(r io.Reader) (string, io.Reader) {
    44  	var buf bytes.Buffer
    45  	_, err := io.Copy(&buf, io.LimitReader(r, 512))
    46  	if err != nil {
    47  		return DefaultType, io.MultiReader(&buf, errReader{err})
    48  	}
    49  	return Match(buf.Bytes()), io.MultiReader(&buf, r)
    50  }
    51  
    52  // errReader is an io.Reader which just returns err.
    53  type errReader struct{ err error }
    54  
    55  func (er errReader) Read([]byte) (int, error) { return 0, er.err }