作者 yangfu

Merge remote-tracking branch 'origin/dev' into test

# Conflicts:
#	conf/dev.conf
#	conf/prod.conf
#	conf/test.conf
#	deploy/k8s/dev/opp.yaml
#	deploy/k8s/prd/opp.yaml
... ... @@ -41,3 +41,6 @@ h5_host = "http://mmm-web-open-test.fjmaimaimai.com"
#审核中心
suplus_approve_host ="http://suplus-approve-dev.fjmaimaimai.com"
#阿里云
cname ="https://media.fjmaimaimai.com/"
\ No newline at end of file
... ...
... ... @@ -43,5 +43,8 @@ h5_host = "http://mmm-web-open-test.fjmaimaimai.com"
#审核中心
suplus_approve_host ="http://suplus-approve-dev.fjmaimaimai.com"
#阿里云 https://media.goexample.live/
cname ="https://media.fjmaimaimai.com/"
#企业平台
BUSINESS_ADMIN_SERVICE_HOST ="${BUSINESS_ADMIN_SERVICE_HOST||http://suplus-business-admin-test.fjmaimaimai.com}"
\ No newline at end of file
... ...
... ... @@ -44,3 +44,6 @@ suplus_approve_host ="https://public-interface.fjmaimaimai.com/approve"
#企业平台
BUSINESS_ADMIN_SERVICE_HOST ="${BUSINESS_ADMIN_SERVICE_HOST||http://suplus-business-admin-prd.fjmaimaimai.com}"
#阿里云
cname ="https://media.fjmaimaimai.com/"
\ No newline at end of file
... ...
... ... @@ -42,5 +42,8 @@ h5_host = "http://mmm-web-open-test.fjmaimaimai.com"
#审核中心
suplus_approve_host ="http://suplus-approve-test.fjmaimaimai.com"
#阿里云
cname ="https://media.fjmaimaimai.com/"
#企业平台
BUSINESS_ADMIN_SERVICE_HOST ="${BUSINESS_ADMIN_SERVICE_HOST||http://suplus-business-admin-test.fjmaimaimai.com}"
\ No newline at end of file
... ...
... ... @@ -159,7 +159,17 @@ func MetricCounter(ctx *context.Context) {
}).Inc()
}
//检查签名
/*检查签名
app 传入 Sign TimeStamp Uuid AccessToken
Sign=》客户端签名串
TimeStamp=》时间戳
UUID字符串=》Uuid(36位)/AccessToken(32位)
//生成签名串与客户端生成的签名串比较
sign="v!(MmM"+TimeStamp + Uuid + AccessToken+"MmM)i^"
signHex = hex.EncodeToString(sha256(sign))
*/
func CheckSign(ctx *context.Context) (result bool) {
var (
h *protocol.RequestHeader
... ... @@ -269,6 +279,10 @@ var LogRequestData = func(ctx *context.Context) {
}
}
func CheckSignMiddleware(ctx *context.Context) {
CheckSign(ctx)
}
func (this *BaseController) Prepare() {
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "*")
... ...
... ... @@ -2,10 +2,14 @@ package aliyun
const (
RegionID = "cn-shanghai"
//AccessKeyID = "LTAI4Fv7TX3UP9nYuofpLHRy"
//AccessKeySecret = "Yx6lSe7JE9KjtWyOV2LSBnjalrGUk6"
AccessKeyID = "LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret = "UyspWwdni55CYQ02hUCint4qY2jNYO"
//公司
AccessKeyID = "LTAI4Fz1LUBW2fXp6QWaJHRS"
AccessKeySecret = "aLZXwK8pgrs10Ws03qcN7NsrSXFVsg"
//个人
//AccessKeyID = "LTAI4FhiZ3UktC6N1u3H5GFC"
//AccessKeySecret = "UyspWwdni55CYQ02hUCint4qY2jNYO"
)
const (
... ...
... ... @@ -20,6 +20,7 @@ var (
type OSSClient struct {
client *oss.Client
Bucket *oss.Bucket
UpAddr UploadAddress
Auth UploadAuth
}
... ... @@ -54,22 +55,35 @@ func NewOSSClient(ep, key, secret, token string) (o *OSSClient, err error) {
}
//简单上传 (通过文件地址)
func (o *OSSClient) PutObjectByUrl(bucketName string, fileName string, url string) error {
func (o *OSSClient) PutObjectByUrl(bucketName string, fileName string, url string, options ...oss.Option) error {
r, err := GetFileFromUrl(url)
if err != nil {
return err
}
return o.PutObject(bucketName, fileName, r)
return o.PutObjectByBucket(bucketName, fileName, r, options...)
}
func (o *OSSClient) PutObjectByUrlDefault(url string) error {
return o.PutObjectByUrl(o.UpAddr.Bucket, o.UpAddr.FileName, url)
func (o *OSSClient) PutObjectByUrlDefault(url string, options ...oss.Option) error {
return o.PutObjectByUrl(o.UpAddr.Bucket, o.UpAddr.FileName, url, options...)
}
//简单上传
func (o *OSSClient) PutObject(bucketName, objKey string, r io.Reader, options ...oss.Option) error {
func (o *OSSClient) PutObjectByBucket(bucketName, objKey string, r io.Reader, options ...oss.Option) error {
bucket, err := o.client.Bucket(bucketName)
if err != nil {
return err
}
return bucket.PutObject(objKey, r, options...)
}
func (o *OSSClient) SetBucket(bucketName string) error {
bucket, err := o.client.Bucket(bucketName)
if err != nil {
return err
}
o.Bucket = bucket
return nil
}
func (o *OSSClient) PutObject(objKey string, r io.Reader, options ...oss.Option) error {
return o.Bucket.PutObject(objKey, r, options...)
}
... ...
... ... @@ -10,7 +10,7 @@ type CreateUploadImageResponse struct {
ImageURL string `json:"imageURL"`
UploadAddress string `json:"uploadAddress"`
UploadAuth string `json:"uploadAuth"`
FileURL string `json:"fileURL"`
FileURL string `json:"fileURL"` //fileURL
}
type CreateUploadImagesRequest struct {
... ...
... ... @@ -45,7 +45,7 @@ func InitVodClient(accessKeyId string, accessKeySecret string) (client *vod.Clie
func CreateUploadVideo(client *vod.Client, r *CreateUploadVideoRequest) (response *CreateUploadVideoResponse, err error) {
request := vod.CreateCreateUploadVideoRequest()
filePath := getFileName(FileVideo, r.FileName)
if filepath.Ext(r.FileName) == "mp3" {
if filepath.Ext(r.FileName) == ".mp3" {
filePath = getFileName(FileVoice, r.FileName)
}
request.Title = filePath
... ... @@ -64,7 +64,7 @@ func CreateUploadVideo(client *vod.Client, r *CreateUploadVideoRequest) (respons
if up, e := ParseUploadAddress(rsp.UploadAddress); e != nil {
log.Error(e)
} else {
response.FileURL = up.GetFileUrl("")
response.FileURL = up.GetFileUrl(beego.AppConfig.String("cname"))
}
return
}
... ... @@ -85,7 +85,7 @@ func RefreshUploadVideo(client *vod.Client, r *RefreshUploadVideoRequest) (respo
if up, e := ParseUploadAddress(rsp.UploadAddress); e != nil {
log.Error(e)
} else {
response.FileURL = up.GetFileUrl("")
response.FileURL = up.GetFileUrl(beego.AppConfig.String("cname"))
}
return
}
... ... @@ -96,7 +96,15 @@ func CreateUploadImage(client *vod.Client, r *CreateUploadImageRequest) (respons
filePath := getFileName(FileImage, r.FileName)
request.ImageType = "default"
request.Title = filePath
if filepath.Ext(r.FileName) == "" {
err = fmt.Errorf("filename:%v invalid", r.FileName)
return
}
request.ImageExt = filepath.Ext(r.FileName)[1:]
if request.ImageExt == "" {
err = fmt.Errorf("filename:%v invalid", r.FileName)
return
}
request.AcceptFormat = "JSON"
//request.StorageLocation = filepath.Base(request.Title)
rsp, err := client.CreateUploadImage(request)
... ... @@ -135,7 +143,7 @@ func getFileName(fileType string, filename string) string {
subfix := path.Ext(filename)
prefix := fmt.Sprintf("%v_%v", time.Now().Unix(), common.RandomString(32))
filename = fmt.Sprintf("%v%v", prefix, subfix)
sourcePath := fmt.Sprintf("%v/%v/%v/%v/%v", beego.BConfig.AppName, beego.BConfig.RunMode, fileType, date, filename)
sourcePath := fmt.Sprintf("%v/%v/%v/%v/%v", beego.BConfig.AppName, beego.BConfig.RunMode, date, fileType, filename)
return sourcePath
}
... ...
... ... @@ -535,16 +535,16 @@ type Speech struct {
Path string `json:"path"`
Duration int `json:"duration"`
VideoId string `json:"videoId"` //videoId
PathBak string `json:"path_bak"` //备份路径
PathBak string `json:"-"` //备份路径
}
//图片
type Picture struct {
Path string `json:"path"`
W int `json:"w"`
H int `json:"h"`
W int `json:"-"` //w
H int `json:"-"` //h
ImageId string `json:"imageId"` //imageId
PathBak string `json:"path_bak"`
PathBak string `json:"-"`
//JobId string `json:"job_id"`
}
... ... @@ -554,7 +554,7 @@ type Video struct {
Cover Cover `json:"cover"` //封面
Duration int `json:"duration"`
VideoId string `json:"videoId"` //videoId
PathBak string `json:"path_bak"`
PathBak string `json:"-"` //
}
//审批配置
... ...
... ... @@ -162,8 +162,9 @@ type QuestionContent struct {
}
type Cover struct {
Path string `json:"path" valid:"Required"`
H int `json:"h"`
W int `json:"w"`
H int `json:"-"`
W int `json:"-"`
ImageId string `json:"imageId"`
}
/*公告列表 BulletinList */
... ...
... ... @@ -23,4 +23,20 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["opp/controllers:H5Controller"] = append(beego.GlobalControllerRouter["opp/controllers:H5Controller"],
beego.ControllerComments{
Method: "ChanceExample",
Router: `/chanceExample`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["opp/controllers:H5Controller"] = append(beego.GlobalControllerRouter["opp/controllers:H5Controller"],
beego.ControllerComments{
Method: "SysCommand",
Router: `/sysCommand`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
}
... ...
... ... @@ -35,7 +35,7 @@ func init() {
beego.AddNamespace(nsV2)
nsH5 := beego.NewNamespace("h5", beego.NSBefore(controllers.LogRequestData), beego.NSBefore(controllers.AllowOption), beego.NSInclude(&controllers.H5Controller{}))
nsVod := beego.NewNamespace("vod", beego.NSBefore(controllers.LogRequestData), beego.NSBefore(controllers.AllowOption), beego.NSInclude(&v1.VodController{}))
nsVod := beego.NewNamespace("vod", beego.NSBefore(controllers.LogRequestData), beego.NSBefore(controllers.AllowOption), beego.NSBefore(controllers.CheckSignMiddleware), beego.NSInclude(&v1.VodController{}))
beego.AddNamespace(nsH5)
beego.AddNamespace(nsVod)
//post 下载文件
... ...
... ... @@ -3,16 +3,17 @@ package contrab
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vod"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/astaxie/beego/orm"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"opp/internal/aliyun"
"opp/internal/utils"
"opp/models"
"opp/protocol"
"path/filepath"
"strings"
)
const LoopSize = 1
const LoopSize = 20
const (
Uploaded = "已上传,跳过"
... ... @@ -31,12 +32,12 @@ func MigrateChanceDataToAliYun() {
log.Info("【迁移机会媒体数据】开始迁移")
defer log.Info("【迁移机会媒体数据】结束迁移")
var (
datas []*models.ChanceData
query = `select * from chance_data order by id limit ?,?`
pageInfo = protocol.PageInfo{PageSize: LoopSize}
)
o := orm.NewOrm()
for {
var datas []*models.ChanceData
if _, e := o.Raw(query, pageInfo.Offset(), pageInfo.PageSize).QueryRows(&datas); e != nil {
if e == orm.ErrNoRows {
break
... ... @@ -44,23 +45,90 @@ func MigrateChanceDataToAliYun() {
log.Error(e)
break
}
log.Info("当前页:", pageInfo.PageIndex, "起始:", pageInfo.Offset(), pageInfo.PageSize, " 行数:", len(datas))
if len(datas) == 0 {
break
}
for i := range datas {
data := datas[i]
//上传图片
data.Images = utils.JsonMarsh(uploadImages(data, data.Images))
//上传视频
data.Videos = utils.JsonMarsh(uploadVideos(data, data.Videos))
//上传音频
//data.Speechs = utils.JsonMarsh(uploadVoice(data, data.Speechs))
//更新数据
o.Update(data)
}
pageInfo.PageIndex += 1
break
//break
}
}
func uploadVideos(d *models.ChanceData, video string) (rsp []protocol.Video) {
utils.JsonUnmarshal(video, &rsp)
if len(rsp) == 0 {
rsp = make([]protocol.Video, 0)
return
}
for i := range rsp {
p := rsp[i]
if len(p.VideoId) > 0 {
printInfo(d, p.Path, Uploaded)
continue
}
var (
err error
auth *aliyun.CreateUploadVideoResponse
authImage *aliyun.CreateUploadImageResponse
vodc *vod.Client
)
vodc, err = aliyun.DefaultVodClient()
if err != nil {
goto ERR
}
//上传视频
auth, err = aliyun.CreateUploadVideo(vodc, &aliyun.CreateUploadVideoRequest{FileName: fixPath(p.Path)})
if err != nil {
goto ERR
}
err = upload(fixPath(p.Path), auth.UploadAddress, auth.UploadAuth)
if err != nil {
goto ERR
}
//备份路径
rsp[i].PathBak = p.Path
rsp[i].VideoId = auth.VideoId
rsp[i].Path = auth.FileURL
printInfo(d, fmt.Sprintf("%v -> %v", p.Path, auth.FileURL), UploadSuccess)
//上传封面
if len(p.Cover.Path) > 0 {
authImage, err = aliyun.CreateUploadImage(vodc, &aliyun.CreateUploadImageRequest{FileName: fixPath(p.Cover.Path)})
if err != nil {
goto ERR
}
err = upload(fixPath(p.Cover.Path), authImage.UploadAddress, authImage.UploadAuth)
if err != nil {
goto ERR
}
printInfo(d, fmt.Sprintf("cover %v -> %v", p.Cover.Path, authImage.ImageURL), UploadSuccess)
rsp[i].Cover.Path = authImage.ImageURL
rsp[i].Cover.ImageId = authImage.ImageId
}
continue
ERR:
{
log.Error("ali vod error:", err)
printInfo(d, p.Path, UploadFail)
continue
}
}
return
}
//上传图片
func uploadImages(d *models.ChanceData, img string) (rsp []protocol.Picture) {
utils.JsonUnmarshal(img, &rsp)
... ... @@ -74,40 +142,115 @@ func uploadImages(d *models.ChanceData, img string) (rsp []protocol.Picture) {
printInfo(d, p.Path, Uploaded)
continue
}
var (
err error
auth *aliyun.CreateUploadImageResponse
vodc *vod.Client
imageRsp *aliyun.CreateUploadImageResponse
client *aliyun.OSSClient
)
vodc, _ = aliyun.DefaultVodClient()
list := filepath.SplitList(p.Path)
if len(list) == 0 {
err = fmt.Errorf("路径无效:%v", p.Path)
vodc, err = aliyun.DefaultVodClient()
if err != nil {
goto ERR
}
auth, err = aliyun.CreateUploadImage(vodc, &aliyun.CreateUploadImageRequest{FileName: fixPath(p.Path)})
if err != nil {
goto ERR
}
err = upload(fixPath(p.Path), auth.UploadAddress, auth.UploadAuth)
if err != nil {
goto ERR
}
imageRsp, err = aliyun.CreateUploadImage(vodc, &aliyun.CreateUploadImageRequest{FileName: list[len(list)-1]})
//备份路径
rsp[i].PathBak = p.Path
rsp[i].ImageId = auth.ImageId
rsp[i].Path = auth.ImageURL
printInfo(d, fmt.Sprintf("%v -> %v", p.Path, auth.ImageURL), UploadSuccess)
continue
ERR:
{
log.Error("ali vod error:", err)
printInfo(d, p.Path, UploadFail)
continue
}
}
return
}
func fixPath(path string) string {
if strings.Index(path, "https:///") >= 0 {
return strings.Replace(path, "https:///", "https://", 1)
}
if strings.Index(path, "https://") >= 0 {
return strings.Replace(path, "https:///", "https://", 1)
}
if strings.Index(path, "https:/") >= 0 {
return strings.Replace(path, "https:/", "https://", 1)
}
if strings.Index(path, "http:///") >= 0 {
return strings.Replace(path, "http:///", "http://", 1)
}
if strings.Index(path, "http://") >= 0 {
return strings.Replace(path, "http:///", "http://", 1)
}
if strings.Index(path, "http:/") >= 0 {
return strings.Replace(path, "http:/", "http://", 1)
}
return path
}
//上传文件
func upload(path string, upAddress, upAuth string, options ...oss.Option) (err error) {
var (
client *aliyun.OSSClient
)
client, err = aliyun.NewStsOSSClient(upAddress, upAuth)
if err != nil {
return
}
err = client.PutObjectByUrlDefault(path, options...)
if err != nil {
return
}
return
}
//上班媒体数据
func uploadVoice(d *models.ChanceData, data string) (rsp []protocol.Speech) {
utils.JsonUnmarshal(data, &rsp)
if len(rsp) == 0 {
rsp = make([]protocol.Speech, 0)
return
}
for i := range rsp {
p := rsp[i]
if len(p.VideoId) > 0 {
printInfo(d, p.Path, Uploaded)
continue
}
var (
err error
auth *aliyun.CreateUploadVideoResponse
vodc *vod.Client
)
vodc, err = aliyun.DefaultVodClient()
if err != nil {
goto ERR
}
client, err = aliyun.NewStsOSSClient(imageRsp.UploadAddress, imageRsp.UploadAuth)
auth, err = aliyun.CreateUploadVideo(vodc, &aliyun.CreateUploadVideoRequest{FileName: p.Path})
if err != nil {
goto ERR
}
err = client.PutObjectByUrlDefault(p.Path)
err = upload(p.Path, auth.UploadAddress, auth.UploadAuth, oss.ContentType("audio/mpeg"))
if err != nil {
goto ERR
}
//备份路径
rsp[i].PathBak = p.Path
rsp[i].ImageId = imageRsp.ImageId
rsp[i].Path = imageRsp.ImageURL
printInfo(d, p.Path, UploadSuccess)
rsp[i].VideoId = auth.VideoId
rsp[i].Path = auth.FileURL
printInfo(d, fmt.Sprintf("%v -> %v", p.Path, auth.FileURL), UploadSuccess)
continue
ERR:
{
... ... @@ -119,12 +262,6 @@ func uploadImages(d *models.ChanceData, img string) (rsp []protocol.Picture) {
return
}
//上班媒体数据
func uploadVoice(d *models.ChanceData, url string) (rp []protocol.Speech) {
//
return nil
}
type ChanceDataExtend struct {
Id int64 `json:"id"`
ChanceId int64 `json:"chance_id"`
... ...
... ... @@ -50,3 +50,22 @@ func Test_MyGetURLUploadInfos(t *testing.T) {
fmt.Printf("%s: %s %s\n", uploadInfo.UploadURL, uploadInfo.Status, uploadInfo.MediaId)
}
}
func Test_FixPath(t *testing.T) {
input := []struct {
Input string
Except string
}{
{Input: "https://123.jpg", Except: "https://123.jpg"},
{Input: "https:///123.jpg", Except: "https://123.jpg"},
{Input: "https:/123.jpg", Except: "https://123.jpg"},
{Input: "http://123.jpg", Except: "http://123.jpg"},
{Input: "http:///123.jpg", Except: "http://123.jpg"},
{Input: "http:/123.jpg", Except: "http://123.jpg"},
}
for i := 0; i < len(input); i++ {
if !strings.EqualFold(fixPath(input[i].Input), input[i].Except) {
t.Fatal("not equal input:", input[i].Input, "except:", input[i].Except, "out:", fixPath(input[i].Input))
}
}
}
... ...
... ... @@ -180,6 +180,7 @@ func CreateUploadImage(header *protocol.RequestHeader, request *aliyun.CreateUpl
request.FileName = aliyun.DefaultImageFileName
}
rsp, err = aliyun.CreateUploadImage(client, request)
rsp.FileURL = rsp.ImageURL
if err != nil {
log.Error(err)
}
... ...