refactor: reorganize modules and add Linux build tooling
This commit is contained in:
11
module/base/fts/internal/logic/config.go
Normal file
11
module/base/fts/internal/logic/config.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"bsm/full/module/base/fts/internal/config"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Config(ctx *gin.Context) {
|
||||
infra.Response.Success(ctx, config.Spec.FtsConfig)
|
||||
}
|
||||
30
module/base/fts/internal/logic/fetch.go
Normal file
30
module/base/fts/internal/logic/fetch.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package logic
|
||||
|
||||
// import (
|
||||
// "context"
|
||||
// "net/http"
|
||||
|
||||
// "bsm/full/module/base/fts/internal/models"
|
||||
// "bsm/full/module/base/fts/internal/svc"
|
||||
// "bsm/full/module/base/fts/internal/types"
|
||||
// "git.apinb.com/bsm-sdk/core/exception"
|
||||
|
||||
// "github.com/zeromicro/go-zero/core/logx"
|
||||
// )
|
||||
|
||||
// func (l *ListLogic) List(in *types.Paginate, r *http.Request) (resp *types.Base, err error) {
|
||||
// // 解析token
|
||||
// claims, err := parseToken(r.Header.Get("Authorization"))
|
||||
// if err != nil {
|
||||
// return nil, exception.ErrAuthNotFound
|
||||
// }
|
||||
// // 获取数据
|
||||
// data, cnt, err := models.GetFileList(in.Offset, in.Size, claims.Identity)
|
||||
// if err != nil {
|
||||
// return nil, exception.ErrDBFatal
|
||||
// }
|
||||
// if cnt == 0 {
|
||||
// return Success(""), nil
|
||||
// }
|
||||
// return Success(data), nil
|
||||
// }
|
||||
134
module/base/fts/internal/logic/handler.go
Normal file
134
module/base/fts/internal/logic/handler.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"bsm/full/module/base/fts/internal/config"
|
||||
"bsm/full/module/base/fts/internal/impl"
|
||||
"bsm/full/module/base/fts/internal/models"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/middleware"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Handler 上传文件
|
||||
func Handler(c *gin.Context) {
|
||||
var (
|
||||
provider = strings.ToLower(c.PostForm("provider"))
|
||||
bucket = strings.ToLower(c.PostForm("bucket"))
|
||||
claims *types.JwtClaims
|
||||
err error
|
||||
)
|
||||
|
||||
claims, err = middleware.ParseAuth(c)
|
||||
if err != nil {
|
||||
log.Printf("获取当前登录用户信息失败: %v\n", err)
|
||||
infra.Response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if provider == "" || bucket == "" {
|
||||
infra.Response.Error(c, errcode.NewError(400, "参数错误"))
|
||||
return
|
||||
}
|
||||
// if !strings.Contains(provider, "local") {
|
||||
// log.Println("provider参数错误")
|
||||
// infra.Response.Error(c, errcode.NewError(400, "provider参数错误"))
|
||||
// return
|
||||
// }
|
||||
|
||||
fh, err := c.FormFile(config.Spec.FtsConfig.InputKey)
|
||||
if err != nil {
|
||||
infra.Response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
fileSize := fh.Size
|
||||
if fileSize > config.Spec.FtsConfig.MaxSize {
|
||||
infra.Response.Error(c, errcode.NewError(400, "文件大小超过限制"))
|
||||
return
|
||||
}
|
||||
|
||||
// 检测是否是允许上传的文件类型
|
||||
fileExt := filepath.Ext(fh.Filename)
|
||||
if !isAllow(fileExt) {
|
||||
log.Println("不允许上传的文件类型:", fileExt)
|
||||
infra.Response.Error(c, errcode.NewError(501, "不允许上传的文件类型"))
|
||||
return
|
||||
}
|
||||
|
||||
fileHash, err := chksum(fh)
|
||||
if err != nil {
|
||||
log.Println("文件校验失败:", err)
|
||||
infra.Response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
record := models.FtsRecord{
|
||||
Identity: utils.UUID(),
|
||||
OwnerID: claims.ID,
|
||||
OwnerIdentity: claims.Identity,
|
||||
Name: fh.Filename,
|
||||
Ext: fileExt,
|
||||
Size: uint64(fileSize),
|
||||
Hash: fileHash,
|
||||
Status: 0,
|
||||
}
|
||||
|
||||
switch provider {
|
||||
case "local":
|
||||
err = LocalUpload(fh, &record, c, bucket)
|
||||
case "minio":
|
||||
err = OssUpload(fh, &record, c, bucket)
|
||||
default:
|
||||
infra.Response.Error(c, errcode.NewError(400, "provider参数错误"))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
infra.Response.Error(c, err)
|
||||
return
|
||||
}
|
||||
if err := impl.DBService.Create(&record).Error; err != nil {
|
||||
infra.Response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
infra.Response.Success(c, record)
|
||||
}
|
||||
|
||||
func chksum(fh *multipart.FileHeader) (string, error) {
|
||||
// 2. 打开文件读取内容
|
||||
file, err := fh.Open()
|
||||
if err != nil {
|
||||
log.Println("multipart err:", err)
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 3. 计算文件哈希值(sha256)
|
||||
hash := sha256.New()
|
||||
if _, err = io.Copy(hash, file); err != nil {
|
||||
log.Println("哈希计算失败:", err)
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(hash.Sum(nil)), nil
|
||||
}
|
||||
|
||||
func isAllow(extName string) bool {
|
||||
for _, allowExt := range config.Spec.FtsConfig.Allows {
|
||||
if extName == allowExt {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
11
module/base/fts/internal/logic/ping.go
Normal file
11
module/base/fts/internal/logic/ping.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Ping
|
||||
func Ping(ctx *gin.Context) {
|
||||
infra.Response.Success(ctx, gin.H{"message": "Pong"})
|
||||
}
|
||||
116
module/base/fts/internal/logic/provider.go
Normal file
116
module/base/fts/internal/logic/provider.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/base/fts/internal/config"
|
||||
"bsm/full/module/base/fts/internal/models"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
|
||||
// LocalUpload 本地上传
|
||||
func LocalUpload(fh *multipart.FileHeader, record *models.FtsRecord, ctx *gin.Context, bucket string) (err error) {
|
||||
subdirpath := NewSubdir(record.OwnerIdentity)
|
||||
saveDir := filepath.Join(config.Spec.Local.UploadDir, bucket, subdirpath)
|
||||
|
||||
// 创建目录并确保权限正确
|
||||
if err = os.MkdirAll(saveDir, 0755); err != nil {
|
||||
log.Println("目录创建失败:", err)
|
||||
infra.Response.Error(ctx, errors.New("目录创建失败"))
|
||||
return
|
||||
}
|
||||
|
||||
// 保存文件到指定路径
|
||||
fileName := utils.ULID() + record.Ext
|
||||
savePath := filepath.Join(saveDir, fileName)
|
||||
|
||||
// 使用自定义方式保存文件,确保权限控制
|
||||
file, err := os.OpenFile(savePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
log.Println("文件创建失败:", err)
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
src, err := fh.Open()
|
||||
if err != nil {
|
||||
log.Println("文件打开失败:", err)
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
if _, err = io.Copy(file, src); err != nil {
|
||||
log.Println("文件保存失败:", err)
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 再次确认文件权限
|
||||
if err = os.Chmod(savePath, 0644); err != nil {
|
||||
log.Printf("警告: 设置文件权限失败: %v", err)
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
record.LocalPath = savePath
|
||||
record.SaveName = fileName
|
||||
record.ResultUrl = config.Spec.Local.Site + "/" + bucket + "/" + subdirpath + "/" + fileName
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OssUpload 上传文件到指定的MinIO存储桶
|
||||
func OssUpload(file *multipart.FileHeader, record *models.FtsRecord, c *gin.Context, bucket string) (err error) {
|
||||
// Initialize minio client object.
|
||||
minioClient, err := minio.New(config.Spec.MinioOss.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(config.Spec.MinioOss.AccessKeyID, config.Spec.MinioOss.AccessKeySecret, ""), // 修正字段名
|
||||
Secure: config.Spec.MinioOss.UseSSL,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置保存格式为: 年/identity/identity后3位+filename
|
||||
subdirpath := NewSubdir(record.OwnerIdentity)
|
||||
fileName := utils.ULID() + record.Ext
|
||||
savePath := filepath.Join(subdirpath, fileName)
|
||||
|
||||
// Open the file
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
_, err = minioClient.PutObject(context.Background(), bucket, savePath, src, file.Size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("err = ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
record.OssPath = savePath
|
||||
fmt.Println("savePath = ", savePath)
|
||||
record.ResultUrl = config.Spec.MinioOss.Site + "/" + bucket + "/" + savePath
|
||||
fmt.Println("record.ResultUrl = ", record.ResultUrl)
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSubdir(identity string) string {
|
||||
ym := time.Now().Format("2006-01")
|
||||
return ym + "/" + identity[0:2]
|
||||
}
|
||||
Reference in New Issue
Block a user