-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathghttp_request_param_file.go
153 lines (139 loc) · 4.8 KB
/
ghttp_request_param_file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright GoFrame Author(https://goframe.org). 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 (
"context"
"io"
"mime/multipart"
"strconv"
"strings"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
)
// init initializes the type converters for *UploadFile.
func init() {
_ = gconv.RegisterTypeConverterFunc(stringToUploadFile)
}
// UploadFile wraps the multipart uploading file with more and convenient features.
type UploadFile struct {
*multipart.FileHeader `json:"-"`
ctx context.Context
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (f UploadFile) MarshalJSON() ([]byte, error) {
return json.Marshal(f.FileHeader)
}
// UploadFiles is an array type of *UploadFile.
type UploadFiles []*UploadFile
// stringToUploadFile is a custom type converter for converting string to *ghttp.UploadFile.
func stringToUploadFile(in string) (*UploadFile, error) {
return &UploadFile{}, nil
}
// Save saves the single uploading file to directory path and returns the saved file name.
//
// The parameter `dirPath` should be a directory path, or it returns error.
//
// Note that it will OVERWRITE the target file if there's already a same name file exist.
func (f *UploadFile) Save(dirPath string, randomlyRename ...bool) (filename string, err error) {
if f == nil || f.FileHeader == nil {
return "", gerror.NewCode(
gcode.CodeMissingParameter,
"file is empty, maybe you retrieve it from invalid field name or form enctype",
)
}
if !gfile.Exists(dirPath) {
if err = gfile.Mkdir(dirPath); err != nil {
return
}
} else if !gfile.IsDir(dirPath) {
return "", gerror.NewCode(gcode.CodeInvalidParameter, `parameter "dirPath" should be a directory path`)
}
file, err := f.Open()
if err != nil {
err = gerror.Wrapf(err, `UploadFile.Open failed`)
return "", err
}
defer file.Close()
name := gfile.Basename(f.Filename)
if len(randomlyRename) > 0 && randomlyRename[0] {
name = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6))
name = name + gfile.Ext(f.Filename)
}
filePath := gfile.Join(dirPath, name)
newFile, err := gfile.Create(filePath)
if err != nil {
return "", err
}
defer newFile.Close()
intlog.Printf(f.ctx, `save upload file: %s`, filePath)
if _, err = io.Copy(newFile, file); err != nil {
err = gerror.Wrapf(err, `io.Copy failed from "%s" to "%s"`, f.Filename, filePath)
return "", err
}
return gfile.Basename(filePath), nil
}
// Save saves all uploading files to specified directory path and returns the saved file names.
//
// The parameter `dirPath` should be a directory path or it returns error.
//
// The parameter `randomlyRename` specifies whether randomly renames all the file names.
func (fs UploadFiles) Save(dirPath string, randomlyRename ...bool) (filenames []string, err error) {
if len(fs) == 0 {
return nil, gerror.NewCode(
gcode.CodeMissingParameter,
"file array is empty, maybe you retrieve it from invalid field name or form enctype",
)
}
for _, f := range fs {
if filename, err := f.Save(dirPath, randomlyRename...); err != nil {
return filenames, err
} else {
filenames = append(filenames, filename)
}
}
return
}
// 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.
//
// It returns nil if retrieving failed or no form file with given name posted.
//
// Note that the `name` 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.
//
// It returns nil if retrieving failed or no form file with given name posted.
//
// Note that the `name` 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{
ctx: r.Context(),
FileHeader: v,
}
}
return uploadFiles
}
return nil
}