2024-02-01 05:44:54 +00:00
|
|
|
|
package common
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/disintegration/imaging"
|
|
|
|
|
"github.com/dubbogo/gost/log/logger"
|
|
|
|
|
"github.com/exhibition-main/internal/config"
|
|
|
|
|
"github.com/exhibition-main/internal/model"
|
|
|
|
|
"github.com/exhibition-main/internal/msg"
|
|
|
|
|
"github.com/exhibition-main/internal/response"
|
|
|
|
|
"github.com/exhibition-main/pkg/logic"
|
|
|
|
|
"github.com/exhibition-main/pkg/utils"
|
|
|
|
|
"github.com/fonchain_enterprise/utils/objstorage"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
uuid "github.com/satori/go.uuid"
|
|
|
|
|
ffmpeg "github.com/u2takey/ffmpeg-go"
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"mime/multipart"
|
|
|
|
|
"net/url"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
wg sync.WaitGroup
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
MediaPath = "./runtime/"
|
|
|
|
|
RouteType = "static/"
|
|
|
|
|
VideoType = "video"
|
|
|
|
|
ImageType = "image"
|
|
|
|
|
PngType = "png"
|
|
|
|
|
ArtworkFilePath = "artwork"
|
|
|
|
|
ArtworkChunkBasePath = "./runtime/tmp/artworks"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func UploadImg(c *gin.Context) {
|
|
|
|
|
var err error
|
|
|
|
|
source := c.PostForm("source")
|
|
|
|
|
mask := c.PostForm("mask")
|
|
|
|
|
action := c.PostForm("action")
|
|
|
|
|
if mask == "" {
|
|
|
|
|
mask = "default"
|
|
|
|
|
}
|
|
|
|
|
mediaType := c.PostForm("type")
|
|
|
|
|
logger.Errorf("UploadImg 1 %+v", mask)
|
|
|
|
|
var BasePath string
|
|
|
|
|
if mediaType == "" || mediaType == ImageType {
|
|
|
|
|
mediaType = ImageType
|
|
|
|
|
}
|
|
|
|
|
BasePath = fmt.Sprintf("%s%s", MediaPath, mediaType)
|
|
|
|
|
//BaseRoute = fmt.Sprintf("%s%s", RouteType, mediaType)
|
|
|
|
|
var isCompress int
|
|
|
|
|
if cStr, ok := c.GetPostForm("is_compress"); ok {
|
|
|
|
|
var errS error
|
|
|
|
|
isCompress, errS = strconv.Atoi(cStr)
|
|
|
|
|
if errS != nil {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, errS.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 2 %+v", mask)
|
|
|
|
|
// 检验参数
|
|
|
|
|
if mask == "" || source == "" {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, msg.INVALID_PARAMS, nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
file, err := c.FormFile("file")
|
|
|
|
|
// 检验文件
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("Upload FormFile err", err)
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 3 %+v", mask)
|
|
|
|
|
// 判断是不是视频或者需要压缩
|
|
|
|
|
var oriUrl string
|
|
|
|
|
if isCompress != 1 && mediaType != "video" && action == "" {
|
|
|
|
|
oriUrl, err = quickBos(file, mediaType, mask, source)
|
|
|
|
|
if err != nil {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Ok, msg.SUCCESS, map[string]interface{}{
|
|
|
|
|
"ori_url": oriUrl,
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 4 %+v", mask)
|
|
|
|
|
//创建文件名
|
|
|
|
|
fileExt := strings.ToLower(path.Ext(file.Filename))
|
|
|
|
|
filename := uuid.NewV4()
|
|
|
|
|
if err != nil {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fileFullName := fmt.Sprintf("%s%s", filename, fileExt)
|
|
|
|
|
//检测文件夹 不存在就创建
|
|
|
|
|
imgPath := fmt.Sprintf("%s/%s/%s", BasePath, source, mask)
|
|
|
|
|
_, err = utils.CheckDirPath(imgPath, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
dst := fmt.Sprintf("%s/%s", imgPath, fileFullName)
|
|
|
|
|
logger.Errorf("UploadImg 5 %+v", mask)
|
|
|
|
|
// 保存文件至指定路径
|
|
|
|
|
err = c.SaveUploadedFile(file, dst)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("Upload FormFile err", err)
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 6 %+v", mask)
|
|
|
|
|
if action == model.ImgActionRotate {
|
|
|
|
|
fileFullName = fmt.Sprintf("%s%s", filename, fileExt)
|
|
|
|
|
newDst := fmt.Sprintf("%s/%s_rotate%v", imgPath, filename, fileExt)
|
|
|
|
|
if err = logic.MakeThumbnail(dst, newDst); err != nil {
|
|
|
|
|
//ResponseQuickMsg(c, e.Failed, e.GetMsg(e.ERROR_ROTATE_IMG), nil)
|
|
|
|
|
//return
|
|
|
|
|
} else {
|
|
|
|
|
_ = os.Remove(dst)
|
|
|
|
|
dst = newDst
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//localUrl := fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fileFullName)
|
2024-07-30 02:28:56 +00:00
|
|
|
|
var data = make(map[string]string, 2)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
//data["ori_url"] = localUrl
|
|
|
|
|
|
|
|
|
|
if int32(isCompress) == 1 {
|
|
|
|
|
//压缩图片并存储在原图路径,命名格式xx.jpg_small.jpg
|
|
|
|
|
fileFullName = fmt.Sprintf("%s_small%s", filename, fileExt)
|
|
|
|
|
newDst := fmt.Sprintf("%s/%s", imgPath, fileFullName)
|
|
|
|
|
//compressUrl := fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fileFullName)
|
|
|
|
|
err = utils.CompressJPG(dst, newDst)
|
|
|
|
|
compressUrl, err := PutBos(newDst, mediaType, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("Upload compress err", err)
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), data)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data["compress_url"] = compressUrl
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 7 %+v", mask)
|
|
|
|
|
// 如果是视频需要截图图片做封面
|
|
|
|
|
if mediaType == VideoType {
|
|
|
|
|
videoCover := fmt.Sprintf("%s/%s", imgPath, filename)
|
|
|
|
|
_, err = GetSnapshot(dst, videoCover, 1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("GetSnapshot err %+v", err.Error())
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, "获取封面失败", err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Errorf("UploadImg 8 %+v", mask)
|
|
|
|
|
logger.Errorf("UploadImg 8.1 videoCover %+v", videoCover)
|
|
|
|
|
//data["cover_url"] = fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fmt.Sprintf("%s.%s", filename, PngType))
|
|
|
|
|
coverUrl, err := PutBos(videoCover+"."+PngType, mediaType, true)
|
|
|
|
|
data["cover_url"] = coverUrl
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("Upload GetSnapshot err", zap.Error(err))
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ossUrl, err := PutBos(dst, mediaType, true)
|
|
|
|
|
if err != nil {
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data["ori_url"] = ossUrl
|
|
|
|
|
response.ResponseQuickMsg(c, msg.Ok, msg.SUCCESS, data)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetSnapshot(videoPath, snapshotPath string, frameNum int) (snapshotName string, err error) {
|
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
|
err = ffmpeg.Input(videoPath).
|
|
|
|
|
Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
|
|
|
|
|
Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
|
|
|
|
|
WithOutput(buf, os.Stdout).
|
|
|
|
|
Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("GetSnapshot Input err:", zap.Error(err))
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
img, err := imaging.Decode(buf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("GetSnapshot Decode err:", zap.Error(err))
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = imaging.Save(img, snapshotPath+"."+PngType)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("GetSnapshot Save err:", zap.Error(err))
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
names := strings.Split(snapshotPath, "\\")
|
|
|
|
|
snapshotName = names[len(names)-1] + "." + PngType
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PutBos(filePath string, mediaType string, needRemove bool) (url string, err error) {
|
2024-09-10 08:47:35 +00:00
|
|
|
|
BOSClient, err := objstorage.NewOSS(config.Data.Bos.AccessKeyId, config.Data.Bos.AccessKeySecret, config.Data.Bos.Endpoint)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
if err != nil {
|
2024-09-10 08:31:33 +00:00
|
|
|
|
logger.Errorf("PutBos NewOSS err ", err)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
err = errors.New(msg.ErrorUploadBos)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
f, err := os.Open(filePath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("PutBos Open err %+v", err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fileBytes, _ := ioutil.ReadAll(f)
|
|
|
|
|
f.Close()
|
|
|
|
|
//删除本地文件
|
|
|
|
|
if needRemove {
|
|
|
|
|
os.Remove(filePath)
|
|
|
|
|
}
|
|
|
|
|
if mediaType == "image" {
|
|
|
|
|
if err = BaiduCheckImage(fileBytes); err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
filePath = strings.Replace(filePath, "./runtime", "", 1)
|
2024-02-19 02:45:33 +00:00
|
|
|
|
var objectName string = fmt.Sprintf("%s/%s%s", config.Data.Bos.BosBaseDir, config.Data.System.Mode, filePath)
|
|
|
|
|
_, err = BOSClient.PutObjectFromBytes(config.Data.Bos.BucketName, objectName, fileBytes)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("PutBos PutObject err %+v", err.Error())
|
|
|
|
|
err = errors.New(msg.ErrorUploadBos)
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-02-19 02:45:33 +00:00
|
|
|
|
url = fmt.Sprintf("%s/%s", config.Data.Bos.CdnHost, objectName)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func quickBos(file *multipart.FileHeader, mediaType string, mask string, source string) (url string, err error) {
|
|
|
|
|
newFile, _ := file.Open()
|
|
|
|
|
defer newFile.Close()
|
|
|
|
|
uuids := uuid.NewV4()
|
|
|
|
|
filePath := fmt.Sprintf("%s/%s/%s/%s%s", mediaType, mask, source, uuids, filepath.Ext(file.Filename))
|
|
|
|
|
fileBytes, _ := ioutil.ReadAll(newFile)
|
|
|
|
|
if mediaType == "image" {
|
|
|
|
|
if err = BaiduCheckImage(fileBytes); err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-19 02:45:33 +00:00
|
|
|
|
var objectName string = fmt.Sprintf("%s/%s/%s", config.Data.Bos.BosBaseDir, config.Data.System.Mode, filePath)
|
2024-09-10 08:47:35 +00:00
|
|
|
|
BOSClient, _ := objstorage.NewOSS(config.Data.Bos.AccessKeyId, config.Data.Bos.AccessKeySecret, config.Data.Bos.Endpoint)
|
2024-02-19 02:45:33 +00:00
|
|
|
|
_, err = BOSClient.PutObjectFromBytes(config.Data.Bos.BucketName, objectName, fileBytes)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("quickBos err", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-02-19 02:45:33 +00:00
|
|
|
|
url = fmt.Sprintf("%s/%s", config.Data.Bos.CdnHost, objectName)
|
2024-02-01 05:44:54 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiduCheckImage 图片鉴黄
|
|
|
|
|
func BaiduCheckImage(imageByte []byte) (err error) {
|
|
|
|
|
return
|
|
|
|
|
var (
|
|
|
|
|
accesstoken string
|
|
|
|
|
response string
|
|
|
|
|
)
|
|
|
|
|
sourcestring := base64.StdEncoding.EncodeToString(imageByte)
|
|
|
|
|
if accesstoken, err = logic.GetImageAccessToken(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
host := "https://aip.baidubce.com/rest/2.0/solution/v1/img_censor/v2/user_defined?access_token=[" + accesstoken + "]"
|
|
|
|
|
if response, err = utils.PostForm(host, url.Values{"image": {sourcestring}}); err != nil {
|
|
|
|
|
logger.Error("user_defined PostForm err", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
var res struct {
|
|
|
|
|
ErrorCode int64 `json:"error_code"`
|
|
|
|
|
ErrorMsg string `json:"error_msg"`
|
|
|
|
|
Conclusion string `json:"conclusion"`
|
|
|
|
|
Log_id uint64 `json:"log_id"`
|
|
|
|
|
IsHitMd5 bool `json:"isHitMd5"`
|
|
|
|
|
ConclusionType int64 `json:"conclusionType"`
|
|
|
|
|
}
|
|
|
|
|
if err = json.Unmarshal([]byte(response), &res); err != nil {
|
|
|
|
|
err = errors.New(msg.JSON_UNMARSHAL)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger.Error("user_defined res", res)
|
|
|
|
|
if res.ErrorCode != 0 || res.ErrorMsg != "" {
|
|
|
|
|
return errors.New(msg.ERROR_BAIDU_FAIL)
|
|
|
|
|
}
|
|
|
|
|
if res.Conclusion != "合规" && res.Conclusion != "疑似" {
|
|
|
|
|
return errors.New(msg.ERROR_BAIDU_IMAGE)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|