github.com/gogf/gf/v2@v2.7.4/net/ghttp/ghttp_request_param_file.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package ghttp 8 9 import ( 10 "context" 11 "io" 12 "mime/multipart" 13 "strconv" 14 "strings" 15 16 "github.com/gogf/gf/v2/errors/gcode" 17 "github.com/gogf/gf/v2/errors/gerror" 18 "github.com/gogf/gf/v2/internal/intlog" 19 "github.com/gogf/gf/v2/internal/json" 20 "github.com/gogf/gf/v2/os/gfile" 21 "github.com/gogf/gf/v2/os/gtime" 22 "github.com/gogf/gf/v2/util/grand" 23 ) 24 25 // UploadFile wraps the multipart uploading file with more and convenient features. 26 type UploadFile struct { 27 *multipart.FileHeader `json:"-"` 28 ctx context.Context 29 } 30 31 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 32 func (f UploadFile) MarshalJSON() ([]byte, error) { 33 return json.Marshal(f.FileHeader) 34 } 35 36 // UploadFiles is an array type of *UploadFile. 37 type UploadFiles []*UploadFile 38 39 // Save saves the single uploading file to directory path and returns the saved file name. 40 // 41 // The parameter `dirPath` should be a directory path, or it returns error. 42 // 43 // Note that it will OVERWRITE the target file if there's already a same name file exist. 44 func (f *UploadFile) Save(dirPath string, randomlyRename ...bool) (filename string, err error) { 45 if f == nil { 46 return "", gerror.NewCode( 47 gcode.CodeMissingParameter, 48 "file is empty, maybe you retrieve it from invalid field name or form enctype", 49 ) 50 } 51 if !gfile.Exists(dirPath) { 52 if err = gfile.Mkdir(dirPath); err != nil { 53 return 54 } 55 } else if !gfile.IsDir(dirPath) { 56 return "", gerror.NewCode(gcode.CodeInvalidParameter, `parameter "dirPath" should be a directory path`) 57 } 58 59 file, err := f.Open() 60 if err != nil { 61 err = gerror.Wrapf(err, `UploadFile.Open failed`) 62 return "", err 63 } 64 defer file.Close() 65 66 name := gfile.Basename(f.Filename) 67 if len(randomlyRename) > 0 && randomlyRename[0] { 68 name = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) 69 name = name + gfile.Ext(f.Filename) 70 } 71 filePath := gfile.Join(dirPath, name) 72 newFile, err := gfile.Create(filePath) 73 if err != nil { 74 return "", err 75 } 76 defer newFile.Close() 77 intlog.Printf(f.ctx, `save upload file: %s`, filePath) 78 if _, err = io.Copy(newFile, file); err != nil { 79 err = gerror.Wrapf(err, `io.Copy failed from "%s" to "%s"`, f.Filename, filePath) 80 return "", err 81 } 82 return gfile.Basename(filePath), nil 83 } 84 85 // Save saves all uploading files to specified directory path and returns the saved file names. 86 // 87 // The parameter `dirPath` should be a directory path or it returns error. 88 // 89 // The parameter `randomlyRename` specifies whether randomly renames all the file names. 90 func (fs UploadFiles) Save(dirPath string, randomlyRename ...bool) (filenames []string, err error) { 91 if len(fs) == 0 { 92 return nil, gerror.NewCode( 93 gcode.CodeMissingParameter, 94 "file array is empty, maybe you retrieve it from invalid field name or form enctype", 95 ) 96 } 97 for _, f := range fs { 98 if filename, err := f.Save(dirPath, randomlyRename...); err != nil { 99 return filenames, err 100 } else { 101 filenames = append(filenames, filename) 102 } 103 } 104 return 105 } 106 107 // GetUploadFile retrieves and returns the uploading file with specified form name. 108 // This function is used for retrieving single uploading file object, which is 109 // uploaded using multipart form content type. 110 // 111 // It returns nil if retrieving failed or no form file with given name posted. 112 // 113 // Note that the `name` is the file field name of the multipart form from client. 114 func (r *Request) GetUploadFile(name string) *UploadFile { 115 uploadFiles := r.GetUploadFiles(name) 116 if len(uploadFiles) > 0 { 117 return uploadFiles[0] 118 } 119 return nil 120 } 121 122 // GetUploadFiles retrieves and returns multiple uploading files with specified form name. 123 // This function is used for retrieving multiple uploading file objects, which are 124 // uploaded using multipart form content type. 125 // 126 // It returns nil if retrieving failed or no form file with given name posted. 127 // 128 // Note that the `name` is the file field name of the multipart form from client. 129 func (r *Request) GetUploadFiles(name string) UploadFiles { 130 multipartFiles := r.GetMultipartFiles(name) 131 if len(multipartFiles) > 0 { 132 uploadFiles := make(UploadFiles, len(multipartFiles)) 133 for k, v := range multipartFiles { 134 uploadFiles[k] = &UploadFile{ 135 ctx: r.Context(), 136 FileHeader: v, 137 } 138 } 139 return uploadFiles 140 } 141 return nil 142 }