增加上传图片
This commit is contained in:
parent
c631a574cd
commit
4cbcf7e512
@ -13,4 +13,5 @@ type Api struct {
|
|||||||
SystemMember // 会员配置
|
SystemMember // 会员配置
|
||||||
SystemSingle // 单项配置
|
SystemSingle // 单项配置
|
||||||
BaseAgreement // 基础数据-协议
|
BaseAgreement // 基础数据-协议
|
||||||
|
Editor // 配置-编辑器
|
||||||
}
|
}
|
||||||
|
|||||||
139
api/controller/Editor.go
Normal file
139
api/controller/Editor.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"hepa-calc-admin-api/api/responses"
|
||||||
|
e "hepa-calc-admin-api/extend/Editor"
|
||||||
|
"hepa-calc-admin-api/extend/aliyun"
|
||||||
|
"hepa-calc-admin-api/utils"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Editor struct{}
|
||||||
|
|
||||||
|
// GetEditorConfig 编辑器-获取配置
|
||||||
|
func (b *Editor) GetEditorConfig(c *gin.Context) {
|
||||||
|
action := c.Query("action")
|
||||||
|
if action == "" {
|
||||||
|
responses.FailWithMessage("缺少参数", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取配置 config
|
||||||
|
if action == "config" {
|
||||||
|
config := e.GetConfig()
|
||||||
|
c.JSON(http.StatusOK, config)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片列表 listImage
|
||||||
|
if action == "listImage" {
|
||||||
|
responses.Ok(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件列表 listFile
|
||||||
|
if action == "listFile" {
|
||||||
|
responses.Ok(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responses.Ok(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditorUpload 编辑器-上传
|
||||||
|
func (b *Editor) EditorUpload(c *gin.Context) {
|
||||||
|
action := c.Query("action")
|
||||||
|
if action == "" {
|
||||||
|
responses.FailWithMessage("缺少参数", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := c.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
responses.FailWithMessage("文件错误", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
responses.FailWithMessage("文件错误", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(f multipart.File) {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}(f)
|
||||||
|
|
||||||
|
// 读取文件内容到字节切片
|
||||||
|
fileBytes, err := io.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
responses.FailWithMessage("文件错误", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加图片水印
|
||||||
|
fileBytes, err = utils.AddWatermarkToImage(fileBytes, "./resource/3061726102564.png")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileType := "jpg"
|
||||||
|
if file.Filename != "" {
|
||||||
|
fileType = utils.GetExtension(file.Filename)
|
||||||
|
if fileType == "" {
|
||||||
|
fileType = "jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
dateTimeString := now.Format("20060102150405") // 当前时间字符串
|
||||||
|
rand.New(rand.NewSource(time.Now().UnixNano())) // 设置随机数
|
||||||
|
|
||||||
|
var ossPath string
|
||||||
|
|
||||||
|
// 上传图片 image
|
||||||
|
if action == "image" {
|
||||||
|
ossPath = "static/images/" + fmt.Sprintf("%d", rand.Intn(9000)+1000) + dateTimeString + "." + fileType
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传视频 video
|
||||||
|
if action == "video" {
|
||||||
|
ossPath = "static/video/" + fmt.Sprintf("%d", rand.Intn(9000)+1000) + dateTimeString + "." + fileType
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件 file
|
||||||
|
if action == "file" {
|
||||||
|
ossPath = "static/file/" + fmt.Sprintf("%d", rand.Intn(9000)+1000) + dateTimeString + "." + fileType
|
||||||
|
}
|
||||||
|
|
||||||
|
if ossPath == "" {
|
||||||
|
responses.FailWithMessage("上传失败", c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传oss
|
||||||
|
_, err = aliyun.PutObjectByte(ossPath, fileBytes)
|
||||||
|
if err != nil {
|
||||||
|
responses.FailWithMessage(err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var g e.UploadDto
|
||||||
|
g.Url = utils.AddOssDomain("/" + ossPath)
|
||||||
|
g.State = "SUCCESS"
|
||||||
|
g.Title = dateTimeString + "." + fileType
|
||||||
|
g.Original = dateTimeString + "." + fileType
|
||||||
|
g.Type = fileType
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, g)
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -271,6 +271,16 @@ func privateRouter(r *gin.Engine, api controller.Api) {
|
|||||||
// 新增单项配置
|
// 新增单项配置
|
||||||
singleGroup.POST("", api.SystemSingle.AddSystemSingle)
|
singleGroup.POST("", api.SystemSingle.AddSystemSingle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 编辑器配置
|
||||||
|
editorGroup := systemGroup.Group("/editor")
|
||||||
|
{
|
||||||
|
// 编辑器-获取配置
|
||||||
|
editorGroup.GET("", api.Editor.GetEditorConfig)
|
||||||
|
|
||||||
|
// 编辑器-上传
|
||||||
|
editorGroup.POST("", api.Editor.EditorUpload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 协议
|
// 协议
|
||||||
|
|||||||
13
config.yaml
13
config.yaml
@ -36,9 +36,9 @@ jwt:
|
|||||||
oss:
|
oss:
|
||||||
oss-access-key: LTAI5tKmFrVCghcxX7yHyGhm
|
oss-access-key: LTAI5tKmFrVCghcxX7yHyGhm
|
||||||
oss-access-key-secret: q1aiIZCJJuf92YbKk2cSXnPES4zx26
|
oss-access-key-secret: q1aiIZCJJuf92YbKk2cSXnPES4zx26
|
||||||
oss-bucket: dev-knowledge
|
oss-bucket: dev-hepa
|
||||||
oss-endpoint: oss-cn-beijing.aliyuncs.com
|
oss-endpoint: oss-cn-beijing.aliyuncs.com
|
||||||
oss-custom-domain-name: https://dev-knowledge.oss-cn-beijing.aliyuncs.com
|
oss-custom-domain-name: https://dev-hepa.oss-cn-beijing.aliyuncs.com
|
||||||
|
|
||||||
# [阿里大鱼短信]
|
# [阿里大鱼短信]
|
||||||
dysms:
|
dysms:
|
||||||
@ -69,4 +69,11 @@ amqp:
|
|||||||
port: 5672
|
port: 5672
|
||||||
user: gdxz_2022rabbitmq
|
user: gdxz_2022rabbitmq
|
||||||
password: qwr2p&¥e@3.2p
|
password: qwr2p&¥e@3.2p
|
||||||
vhost: gdxz_hepa
|
vhost: gdxz_hepa
|
||||||
|
|
||||||
|
# [app]
|
||||||
|
app:
|
||||||
|
apiUrl: https://dev-wx.igandan.com
|
||||||
|
secretKey: RY8pcn04#TSdzHVX6YgWnyCue9!T&QP^
|
||||||
|
imagePrefix: https://dev-doc.igandan.com/app
|
||||||
|
platform: suanyisuan
|
||||||
128
extend/Editor/Editor.go
Normal file
128
extend/Editor/Editor.go
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package Editor
|
||||||
|
|
||||||
|
// Config 定义了上传和管理图片、视频、文件等的配置信息
|
||||||
|
type Config struct {
|
||||||
|
// 图片上传配置
|
||||||
|
ImageActionName string `json:"imageActionName"` // 执行上传图片的action名称,默认值:image
|
||||||
|
ImageFieldName string `json:"imageFieldName"` // 提交的图片表单名称,默认值:file
|
||||||
|
ImageMaxSize int `json:"imageMaxSize"` // 上传大小限制,单位B,默认值:2048000
|
||||||
|
ImageAllowFiles []string `json:"imageAllowFiles"` // 允许的图片格式,默认值:[".png", ".jpg", ".jpeg"]
|
||||||
|
ImageCompressEnable bool `json:"imageCompressEnable"` // 是否压缩图片,默认值:true
|
||||||
|
ImageCompressBorder int `json:"imageCompressBorder"` // 图片压缩最长边限制,默认值:1600
|
||||||
|
ImageInsertAlign string `json:"imageInsertAlign"` // 插入图片时的浮动方式,默认值:none
|
||||||
|
ImageUrlPrefix string `json:"imageUrlPrefix"` // 图片访问路径前缀,默认值:空
|
||||||
|
|
||||||
|
// 涂鸦上传配置
|
||||||
|
ScrawlActionName string `json:"scrawlActionName"` // 执行上传涂鸦的action名称,默认值:scrawl
|
||||||
|
ScrawlFieldName string `json:"scrawlFieldName"` // 提交的涂鸦表单名称,默认值:file
|
||||||
|
ScrawlMaxSize int `json:"scrawlMaxSize"` // 涂鸦上传大小限制,单位B,默认值:2048000
|
||||||
|
ScrawlUrlPrefix string `json:"scrawlUrlPrefix"` // 涂鸦访问路径前缀,默认值:空
|
||||||
|
ScrawlInsertAlign string `json:"scrawlInsertAlign"` // 插入涂鸦时的浮动方式,默认值:none
|
||||||
|
|
||||||
|
// 截图上传配置
|
||||||
|
SnapscreenActionName string `json:"snapscreenActionName"` // 执行上传截图的action名称,默认值:snap
|
||||||
|
SnapscreenUrlPrefix string `json:"snapscreenUrlPrefix"` // 截图访问路径前缀,默认值:空
|
||||||
|
SnapscreenInsertAlign string `json:"snapscreenInsertAlign"` // 插入截图时的浮动方式,默认值:none
|
||||||
|
|
||||||
|
// 图片抓取配置
|
||||||
|
CatcherActionName string `json:"catcherActionName"` // 执行抓取远程图片的action名称,默认值:catch
|
||||||
|
CatcherFieldName string `json:"catcherFieldName"` // 提交的图片列表表单名称,默认值:source
|
||||||
|
CatcherLocalDomain []string `json:"catcherLocalDomain"` // 例外的图片抓取域名,默认值:["127.0.0.1", "localhost"]
|
||||||
|
CatcherUrlPrefix string `json:"catcherUrlPrefix"` // 抓取图片访问路径前缀,默认值:空
|
||||||
|
CatcherMaxSize int `json:"catcherMaxSize"` // 抓取图片上传大小限制,单位B,默认值:10485760
|
||||||
|
CatcherAllowFiles []string `json:"catcherAllowFiles"` // 允许的抓取图片格式,默认值:[".png", ".jpg", ".jpeg"]
|
||||||
|
|
||||||
|
// 视频上传配置
|
||||||
|
VideoActionName string `json:"videoActionName"` // 执行上传视频的action名称,默认值:video
|
||||||
|
VideoFieldName string `json:"videoFieldName"` // 提交的视频表单名称,默认值:file
|
||||||
|
VideoUrlPrefix string `json:"videoUrlPrefix"` // 视频访问路径前缀,默认值:空
|
||||||
|
VideoMaxSize int `json:"videoMaxSize"` // 上传视频大小限制,单位B,默认值:102400000
|
||||||
|
VideoAllowFiles []string `json:"videoAllowFiles"` // 允许的视频格式,默认值:[".mp4"]
|
||||||
|
|
||||||
|
// 文件上传配置
|
||||||
|
FileActionName string `json:"fileActionName"` // 执行上传文件的action名称,默认值:file
|
||||||
|
FileFieldName string `json:"fileFieldName"` // 提交的文件表单名称,默认值:file
|
||||||
|
FileUrlPrefix string `json:"fileUrlPrefix"` // 文件访问路径前缀,默认值:空
|
||||||
|
FileMaxSize int `json:"fileMaxSize"` // 上传文件大小限制,单位B,默认值:104857600
|
||||||
|
FileAllowFiles []string `json:"fileAllowFiles"` // 允许的文件格式,默认值:[".zip", ".pdf", ".doc"]
|
||||||
|
|
||||||
|
// 图片列表配置
|
||||||
|
ImageManagerActionName string `json:"imageManagerActionName"` // 执行图片管理的action名称,默认值:listImage
|
||||||
|
ImageManagerListSize int `json:"imageManagerListSize"` // 每次列出文件数量,默认值:20
|
||||||
|
ImageManagerUrlPrefix string `json:"imageManagerUrlPrefix"` // 图片管理访问路径前缀,默认值:空
|
||||||
|
ImageManagerInsertAlign string `json:"imageManagerInsertAlign"` // 插入的图片浮动方式,默认值:none
|
||||||
|
ImageManagerAllowFiles []string `json:"imageManagerAllowFiles"` // 列出的图片文件类型,默认值:[".jpg", ".png", ".jpeg"]
|
||||||
|
|
||||||
|
// 文件列表配置
|
||||||
|
FileManagerActionName string `json:"fileManagerActionName"` // 执行文件管理的action名称,默认值:listFile
|
||||||
|
FileManagerUrlPrefix string `json:"fileManagerUrlPrefix"` // 指定要列出文件的目录,默认值:空
|
||||||
|
FileManagerListSize int `json:"fileManagerListSize"` // 每次列出文件数量,默认值:20
|
||||||
|
FileManagerAllowFiles []string `json:"fileManagerAllowFiles"` // 列出的文件类型,默认值:[".zip", ".pdf", ".doc"]
|
||||||
|
|
||||||
|
// 公式配置
|
||||||
|
FormulaConfig FormulaConfig `json:"formulaConfig"` // 公式渲染相关配置
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormulaConfig 定义了公式渲染的相关配置
|
||||||
|
type FormulaConfig struct {
|
||||||
|
ImageUrlTemplate string `json:"imageUrlTemplate"` // 公式渲染的图片URL模板
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadDto 上传返回数据
|
||||||
|
type UploadDto struct {
|
||||||
|
Original string `json:"original"`
|
||||||
|
State string `json:"state"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfig 封装方法,返回配置信息
|
||||||
|
func GetConfig() Config {
|
||||||
|
return Config{
|
||||||
|
ImageActionName: "image",
|
||||||
|
ImageFieldName: "file",
|
||||||
|
ImageMaxSize: 8388608,
|
||||||
|
ImageAllowFiles: []string{".jpg", ".png", ".jpeg"},
|
||||||
|
ImageCompressEnable: false,
|
||||||
|
ImageCompressBorder: 5000,
|
||||||
|
ImageInsertAlign: "none",
|
||||||
|
ImageUrlPrefix: "",
|
||||||
|
ScrawlActionName: "crawl",
|
||||||
|
ScrawlFieldName: "file",
|
||||||
|
ScrawlMaxSize: 10485760,
|
||||||
|
ScrawlUrlPrefix: "",
|
||||||
|
ScrawlInsertAlign: "none",
|
||||||
|
SnapscreenActionName: "snap",
|
||||||
|
SnapscreenUrlPrefix: "",
|
||||||
|
SnapscreenInsertAlign: "none",
|
||||||
|
CatcherActionName: "catch",
|
||||||
|
CatcherFieldName: "source",
|
||||||
|
CatcherLocalDomain: []string{"127.0.0.1", "localhost"},
|
||||||
|
CatcherUrlPrefix: "",
|
||||||
|
CatcherMaxSize: 10485760,
|
||||||
|
CatcherAllowFiles: []string{".jpg", ".png", ".jpeg"},
|
||||||
|
VideoActionName: "video",
|
||||||
|
VideoFieldName: "file",
|
||||||
|
VideoUrlPrefix: "",
|
||||||
|
VideoMaxSize: 104857600,
|
||||||
|
VideoAllowFiles: []string{".mp4"},
|
||||||
|
FileActionName: "file",
|
||||||
|
FileFieldName: "file",
|
||||||
|
FileUrlPrefix: "",
|
||||||
|
FileMaxSize: 104857600,
|
||||||
|
FileAllowFiles: []string{".zip", ".pdf", ".doc"},
|
||||||
|
ImageManagerActionName: "listImage",
|
||||||
|
ImageManagerListSize: 20,
|
||||||
|
ImageManagerUrlPrefix: "",
|
||||||
|
ImageManagerInsertAlign: "none",
|
||||||
|
ImageManagerAllowFiles: []string{".jpg", ".png", ".jpeg"},
|
||||||
|
FileManagerActionName: "listFile",
|
||||||
|
FileManagerUrlPrefix: "",
|
||||||
|
FileManagerListSize: 20,
|
||||||
|
FileManagerAllowFiles: []string{".zip", ".pdf", ".doc"},
|
||||||
|
FormulaConfig: FormulaConfig{
|
||||||
|
ImageUrlTemplate: "https://r.latexeasy.com/image.svg?{}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
@ -9,6 +9,7 @@ require (
|
|||||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
|
||||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||||
github.com/bwmarrin/snowflake v0.3.0
|
github.com/bwmarrin/snowflake v0.3.0
|
||||||
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434
|
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/gen2brain/go-fitz v1.23.7
|
github.com/gen2brain/go-fitz v1.23.7
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -57,6 +57,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434 h1:AFIATPhFj7mrISc4z9zEpfm4a8UfwsCWzJ+Je5jA5Rs=
|
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434 h1:AFIATPhFj7mrISc4z9zEpfm4a8UfwsCWzJ+Je5jA5Rs=
|
||||||
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434/go.mod h1:PY9iiFMrFjTzegsqfKCcb+Ekk5/j0ch0sMdBwlT6atI=
|
github.com/facebookarchive/grace v0.0.0-20180706040059-75cf19382434/go.mod h1:PY9iiFMrFjTzegsqfKCcb+Ekk5/j0ch0sMdBwlT6atI=
|
||||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
|
||||||
@ -235,6 +237,7 @@ golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
|||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
|
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
|
||||||
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
@ -325,7 +328,6 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|||||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
|
||||||
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||||
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
|
|||||||
BIN
resource/3061726102564.png
Normal file
BIN
resource/3061726102564.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
43
utils/image.go
Normal file
43
utils/image.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"image"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddWatermarkToImage 添加图片水印
|
||||||
|
func AddWatermarkToImage(fileBytes []byte, watermarkPath string) ([]byte, error) {
|
||||||
|
// 将字节切片转为io.Reader
|
||||||
|
reader := bytes.NewReader(fileBytes)
|
||||||
|
|
||||||
|
// 从字节流中解码图片
|
||||||
|
srcImage, err := imaging.Decode(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("图片解码失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开水印图片
|
||||||
|
watermarkImage, err := imaging.Open(watermarkPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("水印图片加载失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取原图片的宽高,用于水印的位置计算
|
||||||
|
srcBounds := srcImage.Bounds()
|
||||||
|
watermarkBounds := watermarkImage.Bounds()
|
||||||
|
|
||||||
|
// 将水印添加到原图片的右下角
|
||||||
|
offset := image.Pt(srcBounds.Max.X-watermarkBounds.Max.X, srcBounds.Max.Y-watermarkBounds.Max.Y)
|
||||||
|
dstImage := imaging.Overlay(srcImage, watermarkImage, offset, 1.0)
|
||||||
|
|
||||||
|
// 将处理后的图片保存到字节切片中
|
||||||
|
var outputBuffer bytes.Buffer
|
||||||
|
err = imaging.Encode(&outputBuffer, dstImage, imaging.PNG)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("图片编码失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputBuffer.Bytes(), nil
|
||||||
|
}
|
||||||
@ -20,3 +20,13 @@ func AddOssDomain(url string) string {
|
|||||||
}
|
}
|
||||||
return config.C.Oss.OssCustomDomainName + url
|
return config.C.Oss.OssCustomDomainName + url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetExtension 解析并返回字符串中 `.` 后面的部分
|
||||||
|
func GetExtension(s string) string {
|
||||||
|
// 使用 strings.Split 分割字符串
|
||||||
|
parts := strings.Split(s, ".")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user