Compare commits
7 Commits
master
...
269771f982
| Author | SHA1 | Date | |
|---|---|---|---|
| 269771f982 | |||
| 4d8cabacc5 | |||
| 06b3f40905 | |||
| 508f139da2 | |||
| 7b8caaca53 | |||
| 12a743d8da | |||
| 19d62ab927 |
51
Dockerfile
Normal file
51
Dockerfile
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# 阶段1: 构建
|
||||||
|
FROM golang:1.25-alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache git ca-certificates tzdata
|
||||||
|
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
ENV GO111MODULE=on
|
||||||
|
ENV GOPROXY=https://goproxy.cn,direct
|
||||||
|
ENV CGO_ENABLED=0
|
||||||
|
ENV GOTOOLCHAIN=auto
|
||||||
|
ENV GOPRIVATE=gitea.com/red-future/common
|
||||||
|
|
||||||
|
# 配置git使用私有Gitea仓库
|
||||||
|
RUN git config --global url."http://x-token-auth:9b31146aa8c10a7cb4f2e49dcee0934a223be1076289810e1ad98b968066c2bc@116.204.74.41:3000/red-future/common.git".insteadOf "https://gitea.com/red-future/common.git" && \
|
||||||
|
git config --global credential.helper store
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# 复制父目录的 common 模块(因为 go.mod 中使用了本地 replace)
|
||||||
|
COPY ../common /build/common
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go mod download && go mod tidy
|
||||||
|
|
||||||
|
RUN go build -ldflags="-s -w" -o main ./main.go
|
||||||
|
|
||||||
|
# 阶段2: 运行
|
||||||
|
FROM alpine:3.19
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata
|
||||||
|
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=builder /build/main .
|
||||||
|
COPY --from=builder /build/config.yml ./
|
||||||
|
|
||||||
|
RUN mkdir -p /app/resource/log/run \
|
||||||
|
/app/resource/log/server \
|
||||||
|
&& adduser -D -u 1000 appuser \
|
||||||
|
&& chown -R appuser:appuser /app
|
||||||
|
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
EXPOSE 3008
|
||||||
|
|
||||||
|
CMD ["./main"]
|
||||||
38
config.yml
38
config.yml
@@ -13,15 +13,17 @@ database:
|
|||||||
host: "116.204.74.41"
|
host: "116.204.74.41"
|
||||||
port: "15432"
|
port: "15432"
|
||||||
user: "postgres"
|
user: "postgres"
|
||||||
pass: "123456"
|
pass: "Bjang09@686^*^"
|
||||||
name: "oss"
|
name: "oss"
|
||||||
role: "master"
|
role: "master" # (可选)数据库主从角色(master/slave),默认为master。如果不使用应用主从机制请不配置或留空即可。
|
||||||
maxIdle: "5"
|
debug: false # (可选)开启调试模式
|
||||||
maxOpen: "20"
|
dryRun: false # (可选)ORM空跑(只读不写)
|
||||||
maxLifetime: "60s"
|
charset: "utf8" # (可选)数据库编码(如: utf8mb4/utf8/gbk/gb2312),一般设置为utf8mb4。默认为utf8。
|
||||||
charset: "utf8mb4" #数据库编码
|
timezone: "Asia/Shanghai" # (可选)时区配置,例如:Local
|
||||||
debug: true
|
maxIdle: 5 # (可选)连接池最大闲置的连接数(默认10)
|
||||||
dryRun: false #空跑
|
maxOpen: 20 # (可选)连接池最大打开的连接数(默认无限制)
|
||||||
|
maxLifetime: "30s" # (可选)连接对象可重复使用的时间长度(默认30秒)
|
||||||
|
maxIdleConnTime: "30s" # (可选,v2.10新增)连接池中空闲连接的最大生存时间(默认30秒)。可以通过配置文件或SetConnMaxIdleTime方法设置,避免长时间空闲连接占用资源。
|
||||||
createdAt: "created_at" # (可选)自动创建时间字段名称
|
createdAt: "created_at" # (可选)自动创建时间字段名称
|
||||||
updatedAt: "updated_at" # (可选)自动更新时间字段名称
|
updatedAt: "updated_at" # (可选)自动更新时间字段名称
|
||||||
deletedAt: "deleted_at" # (可选)软删除时间字段名称
|
deletedAt: "deleted_at" # (可选)软删除时间字段名称
|
||||||
@@ -30,15 +32,17 @@ database:
|
|||||||
host: "116.204.74.41"
|
host: "116.204.74.41"
|
||||||
port: "15432"
|
port: "15432"
|
||||||
user: "postgres"
|
user: "postgres"
|
||||||
pass: "123456"
|
pass: "Bjang09@686^*^"
|
||||||
name: "oss"
|
name: "oss"
|
||||||
role: "slave"
|
role: "slave" # (可选)数据库主从角色(master/slave),默认为master。如果不使用应用主从机制请不配置或留空即可。
|
||||||
maxIdle: "5"
|
debug: false # (可选)开启调试模式
|
||||||
maxOpen: "20"
|
dryRun: false # (可选)ORM空跑(只读不写)
|
||||||
maxLifetime: "60s"
|
charset: "utf8" # (可选)数据库编码(如: utf8mb4/utf8/gbk/gb2312),一般设置为utf8mb4。默认为utf8。
|
||||||
charset: "utf8mb4" #数据库编码
|
timezone: "Asia/Shanghai" # (可选)时区配置,例如:Local
|
||||||
debug: true
|
maxIdle: 5 # (可选)连接池最大闲置的连接数(默认10)
|
||||||
dryRun: false #空跑
|
maxOpen: 20 # (可选)连接池最大打开的连接数(默认无限制)
|
||||||
|
maxLifetime: "30s" # (可选)连接对象可重复使用的时间长度(默认30秒)
|
||||||
|
maxIdleConnTime: "30s" # (可选,v2.10新增)连接池中空闲连接的最大生存时间(默认30秒)。可以通过配置文件或SetConnMaxIdleTime方法设置,避免长时间空闲连接占用资源。
|
||||||
createdAt: "created_at" # (可选)自动创建时间字段名称
|
createdAt: "created_at" # (可选)自动创建时间字段名称
|
||||||
updatedAt: "updated_at" # (可选)自动更新时间字段名称
|
updatedAt: "updated_at" # (可选)自动更新时间字段名称
|
||||||
deletedAt: "deleted_at" # (可选)软删除时间字段名称
|
deletedAt: "deleted_at" # (可选)软删除时间字段名称
|
||||||
@@ -71,7 +75,7 @@ minio:
|
|||||||
region: "us-east-1" # 与 MinIO 服务端 REGION 一致(默认 us-east-1)
|
region: "us-east-1" # 与 MinIO 服务端 REGION 一致(默认 us-east-1)
|
||||||
|
|
||||||
# 文件上传服务地址,与oss模块minio中的endpoint一致
|
# 文件上传服务地址,与oss模块minio中的endpoint一致
|
||||||
filePrefix: "116.204.74.41:9000"
|
filePrefix: "http://116.204.74.41:9000"
|
||||||
|
|
||||||
# 文件存储初始化容量大小配置
|
# 文件存储初始化容量大小配置
|
||||||
oss:
|
oss:
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package consts
|
|
||||||
|
|
||||||
// MongoDB集合名称常量
|
|
||||||
const (
|
|
||||||
FileCollection = "file"
|
|
||||||
TenantOssTotalCollection = "tenant_oss_total"
|
|
||||||
)
|
|
||||||
7
consts/table_name.go
Normal file
7
consts/table_name.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
const (
|
||||||
|
TableNameFile = "file"
|
||||||
|
TableNameTenantOssTotal = "tenant_oss_total"
|
||||||
|
)
|
||||||
@@ -20,7 +20,7 @@ func (d *file) Insert(ctx context.Context, req *dto.UploadFile) (id int64, err e
|
|||||||
if err = gconv.Struct(req, &res); err != nil {
|
if err = gconv.Struct(req, &res); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := gfdb.DB(ctx).Model(ctx, consts.FileCollection).Insert(&res)
|
r, err := gfdb.DB(ctx).Model(ctx, consts.TableNameFile).Insert(&res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (d *tenantOssTotal) SaveOrUpdate(ctx context.Context, updateData []*dto.Upd
|
|||||||
if err = gconv.Structs(updateData, &res); err != nil {
|
if err = gconv.Structs(updateData, &res); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := gfdb.DB(ctx).Model(ctx, consts.TenantOssTotalCollection).Data(res).OnConflict(entity.TenantOssCol.TenantId).Save()
|
r, err := gfdb.DB(ctx).Model(ctx, consts.TableNameTenantOssTotal).Data(res).OnConflict(entity.TenantOssCol.TenantId).Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ func (d *tenantOssTotal) SaveOrUpdate(ctx context.Context, updateData []*dto.Upd
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *tenantOssTotal) GetOneByTenantId(ctx context.Context, req *dto.GetByTenantIdReq) (res *entity.TenantOssTotal, err error) {
|
func (d *tenantOssTotal) GetOneByTenantId(ctx context.Context, req *dto.GetByTenantIdReq) (res *entity.TenantOssTotal, err error) {
|
||||||
model := gfdb.DB(ctx).Model(ctx, consts.TenantOssTotalCollection).Where(entity.TenantOssCol.TenantId, req.TenantId)
|
model := gfdb.DB(ctx).Model(ctx, consts.TableNameTenantOssTotal).Where(entity.TenantOssCol.TenantId, req.TenantId)
|
||||||
record, err := model.One()
|
record, err := model.One()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module oss
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.com/red-future/common v0.0.4
|
gitea.com/red-future/common v0.0.6
|
||||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.10.0
|
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.10.0
|
||||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.5
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.5
|
||||||
github.com/gogf/gf/v2 v2.10.0
|
github.com/gogf/gf/v2 v2.10.0
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,6 +1,6 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
gitea.com/red-future/common v0.0.4 h1:2QgKc+B2iNfPRncKpmIqIzVwaMGJ3y3dt5v+35YD8SU=
|
gitea.com/red-future/common v0.0.6 h1:2Otksfcy5V5JCBcqd2eRKh4WwZ/iAiIhJZMr6uM1x+Q=
|
||||||
gitea.com/red-future/common v0.0.4/go.mod h1:UI9N5UUjilbMPF7+/lypZSnqDVHigt14300oSRrAyZg=
|
gitea.com/red-future/common v0.0.6/go.mod h1:UI9N5UUjilbMPF7+/lypZSnqDVHigt14300oSRrAyZg=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
|
|||||||
@@ -20,5 +20,8 @@ type UploadFile struct {
|
|||||||
// UploadFileRes 上传文件响应
|
// UploadFileRes 上传文件响应
|
||||||
type UploadFileRes struct {
|
type UploadFileRes struct {
|
||||||
FileURL string `json:"fileURL" dc:"上传地址"`
|
FileURL string `json:"fileURL" dc:"上传地址"`
|
||||||
|
FileSize int `json:"fileSize" dc:"文件大小"`
|
||||||
|
FileName string `json:"fileName" dc:"文件名称"`
|
||||||
|
FileFormat string `json:"fileFormat" dc:"文件格式"`
|
||||||
FileAddressPrefix string `json:"fileAddressPrefix"`
|
FileAddressPrefix string `json:"fileAddressPrefix"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,21 +8,18 @@ import (
|
|||||||
type File struct {
|
type File struct {
|
||||||
beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Bid, Creator, CreatedAt, Updater, UpdatedAt, Deleter, DeletedAt, IsDeleted
|
beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Bid, Creator, CreatedAt, Updater, UpdatedAt, Deleter, DeletedAt, IsDeleted
|
||||||
// 业务字段
|
// 业务字段
|
||||||
TenantId uint64 `orm:"tenant_id" json:"tenantId"` // 租户ID
|
FileURL string `orm:"file_url" json:"fileURL"` // 文件URL
|
||||||
FileURL string `orm:"file_url" json:"fileURL"` // 文件URL
|
|
||||||
FileSize int `orm:"file_size" json:"fileSize"`
|
FileSize int `orm:"file_size" json:"fileSize"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileCol struct {
|
type fileCol struct {
|
||||||
beans.SQLBaseCol
|
beans.SQLBaseCol
|
||||||
TenantId string
|
|
||||||
FileURL string
|
FileURL string
|
||||||
FileSize string
|
FileSize string
|
||||||
}
|
}
|
||||||
|
|
||||||
var FileCol = fileCol{
|
var FileCol = fileCol{
|
||||||
SQLBaseCol: beans.DefSQLBaseCol,
|
SQLBaseCol: beans.DefSQLBaseCol,
|
||||||
TenantId: "tenant_id",
|
|
||||||
FileURL: "file_url",
|
FileURL: "file_url",
|
||||||
FileSize: "file_size",
|
FileSize: "file_size",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,21 +8,18 @@ import (
|
|||||||
type TenantOssTotal struct {
|
type TenantOssTotal struct {
|
||||||
beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
|
beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
|
||||||
// 基础信息
|
// 基础信息
|
||||||
TenantId uint64 `orm:"tenant_id" json:"tenantId"` // 租户ID
|
UsedOssSize int `orm:"used_oss_size" json:"usedOssSize"`
|
||||||
UsedOssSize int `orm:"used_oss_size" json:"usedOssSize"`
|
TotalOssSize int `orm:"total_oss_size" json:"totalOssSize"`
|
||||||
TotalOssSize int `orm:"total_oss_size" json:"totalOssSize"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type tenantOssCol struct {
|
type tenantOssCol struct {
|
||||||
beans.SQLBaseCol
|
beans.SQLBaseCol
|
||||||
TenantId string
|
|
||||||
UsedOssSize string
|
UsedOssSize string
|
||||||
TotalOssSize string
|
TotalOssSize string
|
||||||
}
|
}
|
||||||
|
|
||||||
var TenantOssCol = tenantOssCol{
|
var TenantOssCol = tenantOssCol{
|
||||||
SQLBaseCol: beans.DefSQLBaseCol,
|
SQLBaseCol: beans.DefSQLBaseCol,
|
||||||
TenantId: "tenant_id",
|
|
||||||
UsedOssSize: "used_oss_size",
|
UsedOssSize: "used_oss_size",
|
||||||
TotalOssSize: "total_oss_size",
|
TotalOssSize: "total_oss_size",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto
|
|||||||
// 获取redis-租户存储-锁key
|
// 获取redis-租户存储-锁key
|
||||||
fileLockKey := fmt.Sprintf(consts.FileLockKey, gconv.String(user.TenantId))
|
fileLockKey := fmt.Sprintf(consts.FileLockKey, gconv.String(user.TenantId))
|
||||||
|
|
||||||
success, err := redis.Lock(ctx, fileLockKey, gconv.Int64(time.Minute*1), func(ctx context.Context) error {
|
success, err := utils.Lock(ctx, fileLockKey, gconv.Int64(time.Minute*1), func(ctx context.Context) error {
|
||||||
// 获取redis-租户存储容量总数
|
// 获取redis-租户存储容量总数
|
||||||
get, err := redis.RedisClient().Get(ctx, tenantOssTotalKey)
|
get, err := redis.RedisClient().Get(ctx, tenantOssTotalKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,7 +100,7 @@ func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto
|
|||||||
return nil, gerror.New("存储服务内存不足")
|
return nil, gerror.New("存储服务内存不足")
|
||||||
}
|
}
|
||||||
// 上传图片
|
// 上传图片
|
||||||
fileURL, err := minio.UploadFile(ctx, req.File)
|
fileURL, fileName, fileFormat, err := minio.UploadFile(ctx, req.File)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "上传图片失败: %v", err)
|
glog.Errorf(ctx, "上传图片失败: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -115,8 +115,16 @@ func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// 返回图片url
|
// 返回图片url
|
||||||
return &dto.UploadFileRes{
|
res = &dto.UploadFileRes{
|
||||||
FileURL: fileURL,
|
FileURL: fileURL,
|
||||||
FileAddressPrefix: minio.GetFileAddressPrefix(ctx),
|
FileSize: fileSize,
|
||||||
}, err
|
FileName: fileName,
|
||||||
|
FileFormat: fileFormat,
|
||||||
|
}
|
||||||
|
url, err := utils.GetFileAddressPrefix(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.FileAddressPrefix = url
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ func (s *tenantOssTotal) UpdateUsedOssSize(ctx context.Context) (err error) {
|
|||||||
updateData = append(updateData, e)
|
updateData = append(updateData, e)
|
||||||
|
|
||||||
}
|
}
|
||||||
// 更新数据库
|
if len(updateData) != 0 {
|
||||||
_, err = dao.TenantOssTotal.SaveOrUpdate(ctx, updateData)
|
// 更新数据库
|
||||||
if err != nil {
|
_, err = dao.TenantOssTotal.SaveOrUpdate(ctx, updateData)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user