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 }