github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/helper/filesystem/filesystem.go (about)

     1  package filesystem
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  var contentTypeByExtension map[string]string = 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  // If the file cannot be opened, panics. You should check if the
    32  // file exists, using "filesystem.FileExists()"", before calling this function.
    33  func GetMIMEType(file string) (string, int64) {
    34  	f, err := os.Open(file)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  	defer f.Close()
    39  	buffer := make([]byte, 512)
    40  
    41  	_, errRead := f.Read(buffer)
    42  	if errRead != nil {
    43  		panic(errRead)
    44  	}
    45  
    46  	stat, errStat := f.Stat()
    47  	if errStat != nil {
    48  		panic(errStat)
    49  	}
    50  
    51  	contentType := http.DetectContentType(buffer)
    52  
    53  	if strings.HasPrefix(contentType, "application/octet-stream") || strings.HasPrefix(contentType, "text/plain") {
    54  		for ext, t := range contentTypeByExtension {
    55  			if strings.HasSuffix(file, ext) {
    56  				tmp := t
    57  				if i := strings.Index(contentType, ";"); i != -1 {
    58  					tmp = t + contentType[i:]
    59  				}
    60  				contentType = tmp
    61  				break
    62  			}
    63  		}
    64  	}
    65  
    66  	return contentType, stat.Size()
    67  }
    68  
    69  // FileExists returns true if the file at the given path exists and is readable.
    70  // Returns false if the given file is a directory
    71  func FileExists(file string) bool {
    72  	if stats, err := os.Stat(file); err == nil {
    73  		return !stats.IsDir()
    74  	}
    75  	return false
    76  }
    77  
    78  // IsDirectory returns true if the file at the given path exists, is a directory and is readable.
    79  func IsDirectory(path string) bool {
    80  	if stats, err := os.Stat(path); err == nil {
    81  		return stats.IsDir()
    82  	}
    83  	return false
    84  }
    85  
    86  // Delete the file at the given path.
    87  //
    88  // To avoid panics, you should check if the file exists.
    89  func Delete(path string) {
    90  	err := os.Remove(path)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  }
    95  
    96  // ParseMultipartFiles parse a single file field in a request.
    97  func ParseMultipartFiles(request *http.Request, field string) []File {
    98  	files := []File{}
    99  	for _, fh := range request.MultipartForm.File[field] {
   100  		f, err := fh.Open()
   101  		if err != nil {
   102  			panic(err)
   103  		}
   104  		defer f.Close()
   105  
   106  		fileHeader := make([]byte, 512)
   107  
   108  		if _, err := f.Read(fileHeader); err != nil {
   109  			panic(err)
   110  		}
   111  
   112  		if _, err := f.Seek(0, 0); err != nil {
   113  			panic(err)
   114  		}
   115  
   116  		file := File{
   117  			Header:   fh,
   118  			MIMEType: http.DetectContentType(fileHeader),
   119  			Data:     f,
   120  		}
   121  		files = append(files, file)
   122  	}
   123  	return files
   124  }
   125  
   126  func timestampFileName(name string) string {
   127  	var prefix string
   128  	var extension string
   129  	index := strings.LastIndex(name, ".")
   130  	if index == -1 {
   131  		prefix = name
   132  		extension = ""
   133  	} else {
   134  		prefix = name[:index]
   135  		extension = name[index:]
   136  	}
   137  	return prefix + "-" + strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) + extension
   138  }