goyave.dev/goyave/v4@v4.4.11/util/fsutil/file.go (about) 1 package fsutil 2 3 import ( 4 "io" 5 "mime/multipart" 6 "net/http" 7 "os" 8 ) 9 10 // File represents a file received from client. 11 type File struct { 12 Data multipart.File 13 Header *multipart.FileHeader 14 MIMEType string 15 } 16 17 // Save writes the given file on the disk. 18 // Appends a timestamp to the given file name to avoid duplicate file names. 19 // The file is not readable anymore once saved as its FileReader has already been 20 // closed. 21 // 22 // Creates directories if needed. 23 // 24 // Returns the actual file name. 25 func (file *File) Save(path string, name string) string { 26 name = timestampFileName(name) 27 if err := os.MkdirAll(path, os.ModePerm); err != nil { 28 panic(err) 29 } 30 writer, err := os.OpenFile(path+string(os.PathSeparator)+name, os.O_WRONLY|os.O_CREATE, 0660) 31 if err != nil { 32 panic(err) 33 } 34 defer writer.Close() 35 _, errCopy := io.Copy(writer, file.Data) 36 if errCopy != nil { 37 panic(errCopy) 38 } 39 file.Data.Close() 40 return name 41 } 42 43 // ParseMultipartFiles parse a single file field in a request. 44 func ParseMultipartFiles(request *http.Request, field string) []File { 45 files := []File{} 46 for _, fh := range request.MultipartForm.File[field] { 47 f, err := fh.Open() 48 if err != nil { 49 panic(err) 50 } 51 defer f.Close() 52 53 fileHeader := make([]byte, 512) 54 55 if fh.Size != 0 { 56 if _, err := f.Read(fileHeader); err != nil { 57 panic(err) 58 } 59 60 if _, err := f.Seek(0, 0); err != nil { 61 panic(err) 62 } 63 } 64 65 file := File{ 66 Header: fh, 67 MIMEType: http.DetectContentType(fileHeader), 68 Data: f, 69 } 70 files = append(files, file) 71 } 72 return files 73 }