diff --git a/.example/net/ghttp/client/upload-batch/server.go b/.example/net/ghttp/client/upload-batch/server.go index 0ec144baf..7fc13f8e9 100644 --- a/.example/net/ghttp/client/upload-batch/server.go +++ b/.example/net/ghttp/client/upload-batch/server.go @@ -3,34 +3,16 @@ package main import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" - "github.com/gogf/gf/os/gfile" - "io" ) // Upload uploads files to /tmp . func Upload(r *ghttp.Request) { - saveDir := "/tmp/" - for _, item := range r.GetMultipartFiles("upload-file") { - file, err := item.Open() - if err != nil { - r.Response.Write(err) - return - } - defer file.Close() - - f, err := gfile.Create(saveDir + gfile.Basename(item.Filename)) - if err != nil { - r.Response.Write(err) - return - } - defer f.Close() - - if _, err := io.Copy(f, file); err != nil { - r.Response.Write(err) - return - } + saveDirPath := "/tmp/" + files := r.GetUploadFiles("upload-file") + if err := files.Save(saveDirPath); err != nil { + r.Response.WriteExit(err) } - r.Response.Write("upload successfully") + r.Response.WriteExit("upload successfully") } // UploadShow shows uploading simgle file page. @@ -71,7 +53,7 @@ func UploadShowBatch(r *ghttp.Request) { func main() { s := g.Server() s.Group("/upload", func(group *ghttp.RouterGroup) { - group.ALL("/", Upload) + group.POST("/", Upload) group.ALL("/show", UploadShow) group.ALL("/batch", UploadShowBatch) }) diff --git a/.example/net/ghttp/client/upload/server.go b/.example/net/ghttp/client/upload/server.go index 0ec144baf..7fc13f8e9 100644 --- a/.example/net/ghttp/client/upload/server.go +++ b/.example/net/ghttp/client/upload/server.go @@ -3,34 +3,16 @@ package main import ( "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" - "github.com/gogf/gf/os/gfile" - "io" ) // Upload uploads files to /tmp . func Upload(r *ghttp.Request) { - saveDir := "/tmp/" - for _, item := range r.GetMultipartFiles("upload-file") { - file, err := item.Open() - if err != nil { - r.Response.Write(err) - return - } - defer file.Close() - - f, err := gfile.Create(saveDir + gfile.Basename(item.Filename)) - if err != nil { - r.Response.Write(err) - return - } - defer f.Close() - - if _, err := io.Copy(f, file); err != nil { - r.Response.Write(err) - return - } + saveDirPath := "/tmp/" + files := r.GetUploadFiles("upload-file") + if err := files.Save(saveDirPath); err != nil { + r.Response.WriteExit(err) } - r.Response.Write("upload successfully") + r.Response.WriteExit("upload successfully") } // UploadShow shows uploading simgle file page. @@ -71,7 +53,7 @@ func UploadShowBatch(r *ghttp.Request) { func main() { s := g.Server() s.Group("/upload", func(group *ghttp.RouterGroup) { - group.ALL("/", Upload) + group.POST("/", Upload) group.ALL("/show", UploadShow) group.ALL("/batch", UploadShowBatch) }) diff --git a/net/ghttp/ghttp_request_param_file.go b/net/ghttp/ghttp_request_param_file.go new file mode 100644 index 000000000..d94d12d44 --- /dev/null +++ b/net/ghttp/ghttp_request_param_file.go @@ -0,0 +1,121 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package ghttp + +import ( + "errors" + "github.com/gogf/gf/os/gfile" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/grand" + "io" + "mime/multipart" + "os" + "strconv" + "strings" +) + +// UploadFile wraps the multipart uploading file with more and convenient features. +type UploadFile struct { + *multipart.FileHeader +} + +// UploadFiles is array type of *UploadFile. +type UploadFiles []*UploadFile + +// Save saves the uploading file to specified path. +// The parameter path can be either a directory or a file path. If is a directory, +// it saves the uploading file to the directory using its original name. If is a +// file path, it saves the uploading file to the file path. +// +// The parameter specifies whether randomly renames the file name, which +// make sense if the is a directory. +// +// Note that it will overwrite the target file if there's already a same name file exist. +func (f *UploadFile) Save(path string, randomlyRename ...bool) error { + if f == nil { + return nil + } + file, err := f.Open() + if err != nil { + return err + } + defer file.Close() + + var newFile *os.File + if gfile.IsDir(path) { + filename := gfile.Basename(f.Filename) + if len(randomlyRename) > 0 && randomlyRename[0] { + filename = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) + filename = filename + gfile.Ext(f.Filename) + } + newFile, err = gfile.Create(gfile.Join(path, filename)) + } else { + newFile, err = gfile.Create(path) + } + if err != nil { + return err + } + defer newFile.Close() + + if _, err := io.Copy(newFile, file); err != nil { + return err + } + return nil +} + +// Save saves all the uploading files to specified directory path. +// +// The parameter should be a directory path or it returns error. +// +// The parameter specifies whether randomly renames all the file names. +func (fs UploadFiles) Save(dirPath string, randomlyRename ...bool) error { + if len(fs) == 0 { + return nil + } + if !gfile.IsDir(dirPath) { + return errors.New(`parameter "dirPath" should be a directory path`) + } + var err error + for _, f := range fs { + if err = f.Save(dirPath, randomlyRename...); err != nil { + return err + } + } + return nil +} + +// GetUploadFile retrieves and returns the uploading file with specified form name. +// This function is used for retrieving single uploading file object, which is +// uploaded using multipart form content type. +// +// Note that the is the file field name of the multipart form from client. +func (r *Request) GetUploadFile(name string) *UploadFile { + uploadFiles := r.GetUploadFiles(name) + if len(uploadFiles) > 0 { + return uploadFiles[0] + } + return nil +} + +// GetUploadFiles retrieves and returns multiple uploading files with specified form name. +// This function is used for retrieving multiple uploading file objects, which are +// uploaded using multipart form content type. +// +// Note that the is the file field name of the multipart form from client. +func (r *Request) GetUploadFiles(name string) UploadFiles { + multipartFiles := r.GetMultipartFiles(name) + if len(multipartFiles) > 0 { + uploadFiles := make(UploadFiles, len(multipartFiles)) + for k, v := range multipartFiles { + uploadFiles[k] = &UploadFile{ + FileHeader: v, + } + } + return uploadFiles + } + return nil +}