exhibition-main/pkg/service/common/common.go

327 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"mime/multipart"
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"sync"
"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"
)
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)
var data = make(map[string]string, 2)
//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) {
BOSClient, err := objstorage.NewOSS(config.Data.Bos.AccessKeyId, config.Data.Bos.AccessKeySecret, config.Data.Bos.Endpoint)
if err != nil {
logger.Errorf("PutBos NewOSS err ", err)
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)
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)
if err != nil {
logger.Errorf("PutBos PutObject err %+v", err.Error())
err = errors.New(msg.ErrorUploadBos)
return
}
url = fmt.Sprintf("%s/%s", config.Data.Bos.CdnHost, objectName)
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
}
}
var objectName string = fmt.Sprintf("%s/%s/%s", config.Data.Bos.BosBaseDir, config.Data.System.Mode, filePath)
BOSClient, _ := objstorage.NewOSS(config.Data.Bos.AccessKeyId, config.Data.Bos.AccessKeySecret, config.Data.Bos.Endpoint)
_, err = BOSClient.PutObjectFromBytes(config.Data.Bos.BucketName, objectName, fileBytes)
if err != nil {
logger.Errorf("quickBos err", err)
return
}
url = fmt.Sprintf("%s/%s", config.Data.Bos.CdnHost, objectName)
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
}
// 图片转url
func UploadFile(fileBytes []byte) (url string, err error) {
mask := "default"
source := "国展报名"
uuids := uuid.NewV4()
filePath := fmt.Sprintf("%s/%s/%s.png", mask, source, uuids)
var objectName string = fmt.Sprintf("%s/%s/%s", config.Data.Bos.BosBaseDir, config.Data.System.Mode, filePath)
BOSClient, _ := objstorage.NewOSS(config.Data.Bos.AccessKeyId, config.Data.Bos.AccessKeySecret, config.Data.Bos.Endpoint)
_, err = BOSClient.PutObjectFromBytes(config.Data.Bos.BucketName, objectName, fileBytes)
if err != nil {
logger.Errorf("UploadImg PutObjectFromBytes err", err)
return "", err
}
url = fmt.Sprintf("%s/%s", config.Data.Bos.CdnHost, objectName)
return
}