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  }