/
file_upload.go
127 lines (121 loc) · 3.99 KB
/
file_upload.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
package file
import (
"crypto/md5"
"encoding/hex"
FileConstant "github.com/herman-hang/herman/application/constants/admin/file"
"github.com/herman-hang/herman/application/repositories"
"github.com/herman-hang/herman/kernel/app"
"io/ioutil"
"mime/multipart"
"path/filepath"
"strings"
"time"
)
// Exec 执行文件上传
// @param files []*multipart.FileHeader 文件对象切片
// @param creatorId uint 创建者id
// @return fileInfos existFileInfos 待记录的文件信息,已存在的文件信息
func Exec(files []*multipart.FileHeader, creatorId uint) (fileInfos []map[string]interface{}, existFileInfos []map[string]interface{}) {
for _, fileItem := range files {
// hash值
fileHash, content := calculateHash(fileItem)
// 文件扩展名
fileExt := strings.ToLower(filepath.Ext(fileItem.Filename))
// 文件类型
fileType := fileItem.Header.Get("Content-Type")
// 判断当前文件是否存在,不存在则上传
find, _ := repositories.File().Find(map[string]interface{}{"hash": fileHash}, []string{"id", "file_name", "file_type", "file_ext", "file_size"})
if len(find) > 0 {
existFileInfos = append(existFileInfos, find)
} else {
// 适配驱动上传
filePath := adaptiveUpload(fileHash, content)
// 待记录的文件信息
fileInfos = append(fileInfos, map[string]interface{}{
"drive": app.Config.FileStorage.Drive,
"creatorId": creatorId,
"fileName": fileItem.Filename,
"fileExt": fileExt,
"fileType": fileType,
"filePath": filePath,
"hash": fileHash,
"fileSize": fileItem.Size,
})
}
}
return fileInfos, existFileInfos
}
// calculateHash 计算文件Hash值
// @param *multipart.FileHeader file 文件对象
// @return hash content 返回一个hash值和一个文件流
func calculateHash(file *multipart.FileHeader) (hash string, content []byte) {
fp, err := file.Open()
if err != nil {
panic(FileConstant.OpenFileFail)
}
defer func(fp multipart.File) {
if err := fp.Close(); err != nil {
panic(FileConstant.CloseFileFail)
}
}(fp)
content, err = ioutil.ReadAll(fp)
if err != nil {
panic(FileConstant.ReadFileFail)
}
hashed := md5.New()
hashed.Write(content)
return hex.EncodeToString(hashed.Sum(nil)), content
}
// adaptiveUpload 适配驱动上传文件
// @param string fileHash 文件hash值
// @param []byte content 文件流
// @return filePath 返回一个文件路径
func adaptiveUpload(fileHash string, content []byte) (filePath string) {
folderName := time.Now().Format("2006/01/02")
switch app.Config.FileStorage.Drive {
case "local":
filePath = mkdir(app.Config.FileStorage.Local.Path) + "/" + fileHash
fileDrive := NewLocalOSS()
go func() {
if err := fileDrive.Upload(filePath, content); err != nil {
app.Log.Error(FileConstant.UploadFail)
}
}()
case "oss":
aliOss := app.Config.FileStorage.Oss
filePath = filepath.Join(aliOss.Path, folderName) + "/" + fileHash
fileDrive, err := NewAliOSS(aliOss.Endpoint, aliOss.AccessKeyId, aliOss.AccessKeySecret, aliOss.Bucket)
if err != nil {
panic(FileConstant.NewObjectFail)
}
go func() {
if err := fileDrive.Upload(filePath, content); err != nil {
app.Log.Error(FileConstant.UploadFail)
}
}()
case "cos":
cos := app.Config.FileStorage.Cos
filePath = filepath.Join(cos.Path, folderName) + "/" + fileHash
fileDrive, err := NewTencentCOS(cos.Region, cos.AppId, cos.SecretId, cos.SecretKey, cos.Bucket)
if err != nil {
panic(FileConstant.UploadFail)
}
go func() {
if err := fileDrive.Upload(filePath, content); err != nil {
app.Log.Error(FileConstant.UploadFail)
}
}()
case "qiniu":
qiniu := app.Config.FileStorage.Qiniu
filePath = filepath.Join(qiniu.Path, folderName) + "/" + fileHash
fileDrive := NewQiniu(qiniu.AccessKey, qiniu.SecretKey, qiniu.Bucket, qiniu.Domain)
go func() {
if err := fileDrive.Upload(filePath, content); err != nil {
app.Log.Error(FileConstant.UploadFail)
}
}()
default:
panic(FileConstant.ConfigFileDriveError)
}
return strings.ReplaceAll(filePath, "\\", "/")
}