goyave.dev/goyave/v4@v4.4.11/util/fsutil/fsutil.go (about)

     1  package fsutil
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  var contentTypeByExtension = map[string]string{
    12  	".jsonld": "application/ld+json",
    13  	".json":   "application/json",
    14  	".js":     "text/javascript",
    15  	".mjs":    "text/javascript",
    16  	".css":    "text/css",
    17  }
    18  
    19  // GetFileExtension returns the last part of a file name.
    20  // If the file doesn't have an extension, returns an empty string.
    21  func GetFileExtension(file string) string {
    22  	index := strings.LastIndex(file, ".")
    23  	if index == -1 {
    24  		return ""
    25  	}
    26  	return file[index+1:]
    27  }
    28  
    29  // GetMIMEType get the mime type and size of the given file.
    30  //
    31  // This function calls `http.DetectContentType`. If the detected content type
    32  // could not be determined or if it's a text file, `GetMIMEType` will attempt to
    33  // detect the MIME type based on the file extension. The following extensions are
    34  // supported:
    35  //   - `.jsonld`: "application/ld+json"
    36  //   - `.json`: "application/json"
    37  //   - `.js` / `.mjs`: "text/javascript"
    38  //   - `.css`: "text/css"
    39  //
    40  // If a specific MIME type cannot be determined, returns "application/octet-stream" as a fallback.
    41  //
    42  // If the file cannot be opened, panics. You should check if the
    43  // file exists, using "fsutil.FileExists()"", before calling this function.
    44  func GetMIMEType(file string) (string, int64) {
    45  	f, err := os.Open(file)
    46  	if err != nil {
    47  		panic(err)
    48  	}
    49  	defer f.Close()
    50  
    51  	stat, errStat := f.Stat()
    52  	if errStat != nil {
    53  		panic(errStat)
    54  	}
    55  
    56  	size := stat.Size()
    57  
    58  	buffer := make([]byte, 512)
    59  	contentType := "application/octet-stream"
    60  
    61  	if size != 0 {
    62  		_, err = f.Read(buffer)
    63  		if err != nil {
    64  			panic(err)
    65  		}
    66  
    67  		contentType = http.DetectContentType(buffer)
    68  	}
    69  
    70  	if strings.HasPrefix(contentType, "application/octet-stream") || strings.HasPrefix(contentType, "text/plain") {
    71  		for ext, t := range contentTypeByExtension {
    72  			if strings.HasSuffix(file, ext) {
    73  				tmp := t
    74  				if i := strings.Index(contentType, ";"); i != -1 {
    75  					tmp = t + contentType[i:]
    76  				}
    77  				contentType = tmp
    78  				break
    79  			}
    80  		}
    81  	}
    82  
    83  	return contentType, size
    84  }
    85  
    86  // FileExists returns true if the file at the given path exists and is readable.
    87  // Returns false if the given file is a directory.
    88  func FileExists(file string) bool {
    89  	if stats, err := os.Stat(file); err == nil {
    90  		return !stats.IsDir()
    91  	}
    92  	return false
    93  }
    94  
    95  // IsDirectory returns true if the file at the given path exists, is a directory and is readable.
    96  func IsDirectory(path string) bool {
    97  	if stats, err := os.Stat(path); err == nil {
    98  		return stats.IsDir()
    99  	}
   100  	return false
   101  }
   102  
   103  // Delete the file at the given path.
   104  //
   105  // To avoid panics, you should check if the file exists.
   106  func Delete(path string) {
   107  	err := os.Remove(path)
   108  	if err != nil {
   109  		panic(err)
   110  	}
   111  }
   112  
   113  func timestampFileName(name string) string {
   114  	var prefix string
   115  	var extension string
   116  	index := strings.LastIndex(name, ".")
   117  	if index == -1 {
   118  		prefix = name
   119  		extension = ""
   120  	} else {
   121  		prefix = name[:index]
   122  		extension = name[index:]
   123  	}
   124  	return prefix + "-" + strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) + extension
   125  }