| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- package controllers
- import (
- "fmt"
- "io/ioutil"
- "os"
- "strconv"
- "strings"
- "time"
- "github.com/astaxie/beego"
- validation "github.com/go-ozzo/ozzo-validation/v4"
- "lc/common/models"
- "lc/common/mqtt"
- "lc/common/protocol"
- "lc/common/util"
- )
- type CameraController struct {
- BaseController
- }
- type ReqCamera struct {
- Code string `json:"code"` //设备编号,禁止修改
- GID string `json:"gid"` //网关ID
- Tenant string `json:"tenant"` //租户ID
- Name string `json:"name"` //设备名称
- Brand int `json:"brand"` //品牌
- Model int `json:"model"` //型号
- DevType int `json:"devtype"` //设备类型
- State int `json:"state"` //1启用,0禁用
- }
- func (a ReqCamera) Validate() error {
- return validation.ValidateStruct(&a,
- validation.Field(&a.Code, validation.Required, validation.Length(4, 32)),
- validation.Field(&a.GID, validation.Required, validation.Length(4, 32)),
- validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)),
- validation.Field(&a.State, validation.In(0, 1)),
- )
- }
- type Camera struct {
- Code string `json:"code"` //设备编号,禁止修改
- GID string `json:"gid"` //网关ID
- Name string `json:"name"` //设备名称
- Brand int `json:"brand"` //品牌
- Model int `json:"model"` //型号
- DevType int `json:"devtype"` //设备类型
- State int `json:"state"` //1启用,0禁用
- }
- func (a Camera) Validate() error {
- return validation.ValidateStruct(&a,
- validation.Field(&a.Code, validation.Required, validation.Length(4, 32)),
- validation.Field(&a.GID, validation.Required, validation.Length(4, 32)),
- validation.Field(&a.State, validation.In(0, 1)),
- )
- }
- type ReqImportCamera struct {
- Tenant string `json:"tenant"` //租户ID
- List []Camera `json:"list"` //列表
- }
- func (a ReqImportCamera) Validate() error {
- var rules []*validation.FieldRules
- rules = append(rules, validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)))
- rules = append(rules, validation.Field(&a.List, validation.Required))
- return validation.ValidateStruct(&a, rules...)
- }
- type RespSnapshotUrl struct {
- Code string `json:"code"`
- Date string `json:"date"`
- URLs []string `json:"urls"`
- }
- type PresetInfo struct {
- Token string `json:"token"`
- Name string `json:"name"`
- File string `json:"file"`
- }
- type RespPresetInfo struct {
- Code string `json:"code"`
- Data []PresetInfo `json:"data"`
- }
- // CreateCamera @Title 创建摄像头或一键告警设备
- // @Description 创建摄像头或一键告警设备
- // @Param body controllers.ReqCamera true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/create [post]
- func (o *CameraController) CreateCamera() {
- var obj ReqCamera
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- oo := models.CameraDevice{
- ID: obj.Code, //设备ID,DID
- Name: obj.Name, //集控器名称
- GID: obj.GID, //网关ID
- DevType: obj.DevType,
- Tenant: obj.Tenant,
- State: obj.State, //1启用,0禁用
- }
- if err := oo.SaveFromWeb(); err != nil {
- o.Response(Failure, fmt.Sprintf("数据插入失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", oo.ID)
- }
- // UpdateCamera @Title 更新摄像头或一键告警设备
- // @Description 更新摄像头或一键告警设备
- // @Param body controllers.ReqCamera true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/update [post]
- func (o *CameraController) UpdateCamera() {
- var obj ReqCamera
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- oo := models.CameraDevice{
- ID: obj.Code, //设备ID,DID
- Name: obj.Name, //集控器名称
- GID: obj.GID, //网关ID
- DevType: obj.DevType,
- Tenant: obj.Tenant,
- State: obj.State, //1启用,0禁用
- }
- if err := oo.SaveFromWeb(); err != nil {
- o.Response(Failure, fmt.Sprintf("数据更新失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", oo.ID)
- }
- // DeleteCamera @Title 删除摄像头或一键告警设备
- // @Description 删除摄像头或一键告警设备
- // @Param code query string true "设备ID"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/delete [post]
- func (o *CameraController) DeleteCamera() {
- code := strings.Trim(o.GetString("code"), " ")
- if err := validation.Validate(code, validation.Required, validation.Length(4, 100)); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- c := models.CameraDevice{
- ID: code,
- }
- if err := c.Delete(); err != nil {
- beego.Error(fmt.Sprintf("删除失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("数据删除失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", c.ID)
- }
- // ImportCamera @Title 导入摄像头或一键告警设备
- // @Description 导入摄像头或一键告警设备
- // @Param body controllers.ReqImportCamera true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/import [post]
- func (o *CameraController) ImportCamera() {
- var obj ReqImportCamera
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- var resp []RespImport
- for _, v := range obj.List {
- var aresp RespImport
- aresp.Code = v.Code
- oo := models.CameraDevice{
- ID: v.Code, //设备ID,DID
- Name: v.Name, //集控器名称
- GID: v.GID, //网关ID
- DevType: v.DevType,
- Tenant: obj.Tenant,
- State: v.State, //1启用,0禁用
- }
- err := oo.SaveFromWeb()
- if err != nil {
- aresp.Error = err.Error()
- beego.Error(fmt.Sprintf("数据导入失败,code=%s,失败原因:%s", v.Code, err.Error()))
- }
- resp = append(resp, aresp)
- }
- o.Response(Success, "成功", resp)
- }
- // UpdateState @Title 更新摄像机或一键告警设备启用禁用状态
- // @Description 更新摄像机或一键告警设备启用禁用状态
- // @Param body controllers.ProgramsState true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/update/state [POST]
- func (o *CameraController) UpdateState() {
- code := o.GetString("code")
- state, err := o.GetUint8("state", 0)
- if code == "" || state > 1 || err != nil {
- beego.Error("参数错误")
- o.Response(Failure, "参数错误", nil)
- return
- }
- err = models.CameraDeviceUpdateState(code, int(state))
- if err != nil {
- beego.Error("CameraController.UpdateState:更新设备状态错误:", err.Error())
- o.Response(Failure, "失败", err.Error())
- return
- }
- o.Response(Success, "成功", code)
- }
- // SelectPresets @Title 获取预置位信息
- // @Description 获取预置位信息
- // @Param body controllers.ProgramsState true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/select/presets [get]
- func (o *CameraController) SelectPresets() {
- code := o.GetString("code")
- if code == "" {
- beego.Error("参数错误")
- o.Response(Failure, "参数错误", nil)
- return
- }
- arr, err := models.GetPresetsByID(code)
- if err != nil {
- beego.Error("CameraController.SelectPresets:获取预置位错误:", err.Error())
- o.Response(Failure, "失败", err.Error())
- return
- }
- presetdir := BaseUrl + string(os.PathSeparator) + "file" + string(os.PathSeparator) + "preset" + string(os.PathSeparator)
- var ret RespPresetInfo
- ret.Code = code
- for _, v := range arr {
- ret.Data = append(ret.Data, PresetInfo{Token: v.Token, Name: v.Name, File: presetdir + v.File})
- }
- o.Response(Success, "成功", ret)
- }
- // ControlPTZ @Title 球机PTZ控制
- // @Description 球机PTZ控制
- // @router /v1/control/ptz [get]
- func (o *CameraController) ControlPTZ() {
- code := o.GetString("code") //设备编号
- direction, err0 := o.GetUint8("direction") //方向,0~6
- speed, err1 := o.GetUint8("speed") //速度
- if err0 != nil || err1 != nil || code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- if direction < 0 || direction > 6 || speed < 1 {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- ci, err := models.GetCameraInfoByID(code)
- if err != nil {
- beego.Error(fmt.Sprintf("找不到该摄像机的配置[ID=%s] err=%s", code, err))
- o.Response(Failure, fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code), nil)
- return
- }
- var ptz protocol.Pack_PTZMoveInfo
- if str, err := ptz.EnCode(code, ci.GID, "", GetNextUint64(), direction, speed); err == nil {
- topic := GetTopic(ci.Tenant, protocol.DT_IPC, code, protocol.TP_ONVIF_PTZ)
- err := GetMqttHandler().PublishString(topic, str, mqtt.AtMostOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()))
- o.Response(Failure, fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()), nil)
- return
- } else {
- beego.Info(fmt.Sprintf("发布PTZ主题[%s]成功,内容:%s", topic, str))
- }
- }
- o.Response(Success, "成功", nil)
- }
- // ControlPTZHome @Title 球机HOME设置和跳转
- // @Description 球机HOME设置和跳转
- // @router /v1/control/ptzhome [get]
- func (o *CameraController) ControlPTZHome() {
- code := o.GetString("code") //设备编号
- flag, err0 := o.GetUint8("flag") //0跳转,1设置
- if err0 != nil || code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- if flag == 1 {
- flag = 4
- } else {
- flag = 5
- }
- ci, err := models.GetCameraInfoByID(code)
- if err != nil {
- beego.Error(fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code))
- o.Response(Failure, fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code), nil)
- return
- }
- var ptzc protocol.Pack_PTZCommonInfo
- if str, err := ptzc.EnCode(code, ci.GID, "", "1", "home", GetNextUint64(), int(flag)); err == nil {
- topic := GetTopic(ci.Tenant, protocol.DT_IPC, code, protocol.TP_ONVIF_PTZ_COMM)
- err := GetMqttHandler().PublishString(topic, str, mqtt.AtMostOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()))
- o.Response(Failure, fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()), nil)
- return
- }
- }
- o.Response(Success, "成功", nil)
- }
- //case 25: //设置home
- //var ptzc protocol.Pack_PTZCommonInfo
- //if str, err := ptzc.EnCode(SXTDID, GID, "", "10", "旁边的小路口", GetNextUint64(), 4); err == nil {
- //mc.Publish(GetTopic(SXTDID, protocol.DT_IPC, protocol.TP_ONVIF_PTZ_COMM), 0x00, false, str).Wait()
- //}
- //case 26: //跳转home
- //var ptzc protocol.Pack_PTZCommonInfo
- //if str, err := ptzc.EnCode(SXTDID, GID, "", "10", "旁边的小路口", GetNextUint64(), 5); err == nil {
- //mc.Publish(GetTopic(SXTDID, protocol.DT_IPC, protocol.TP_ONVIF_PTZ_COMM), 0x00, false, str).Wait()
- //}
- // ControlSnapshot @Title 抓图命令
- // @Description 抓图命令
- // @router /v1/control/snapshot [get]
- func (o *CameraController) ControlSnapshot() {
- code := o.GetString("code") //设备编号
- if code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- ci, err := models.GetCameraInfoByID(code)
- if err != nil {
- beego.Error(fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code))
- o.Response(Failure, fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code), nil)
- return
- }
- var pc protocol.Pack_MediaCommonInfo
- if str, err := pc.EnCode(code, ci.GID, "", GetNextUint64(), 0 /*0:抓图*/); err == nil {
- topic := GetTopic(ci.Tenant, protocol.DT_IPC, code, protocol.TP_ONVIF_SNAPSHOT)
- err := GetMqttHandler().PublishString(topic, str, mqtt.AtMostOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()))
- o.Response(Failure, fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()), nil)
- return
- }
- }
- o.Response(Success, "成功", nil)
- }
- // Video @Title 视频推流、停止推流
- // @Description 视频推流、停止推流
- // @router /v1/control/video [get]
- func (o *CameraController) Video() {
- code := o.GetString("code") //设备编号
- flag, err := o.GetUint8("flag") //方向,0~6
- if err != nil || code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- if flag != 1 && flag != 2 {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- ci, err := models.GetCameraInfoByID(code)
- if err != nil {
- beego.Error(fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code))
- o.Response(Failure, fmt.Sprintf("找不到该摄像机的配置[ID=%s]", code), nil)
- return
- }
- //开启GB28181协议的设备,视频流直接走GB28181服务,不需要边缘端用ffmpeg拉流、推流
- if ci.Gb28181 {
- beego.Debug(fmt.Sprintf("该摄象机配置了GB28181,不需要ffmpeg推流[设备ID=%s]", code))
- o.Response(Success, "成功", nil)
- return
- }
- var pc protocol.Pack_MediaCommonInfo
- if str, err := pc.EnCode(code, ci.GID, "", GetNextUint64(), int(flag)); err == nil {
- topic := GetTopic(ci.Tenant, protocol.DT_IPC, code, protocol.TP_ONVIF_VIDEO)
- err := GetMqttHandler().PublishString(topic, str, mqtt.AtMostOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()))
- o.Response(Failure, fmt.Sprintf("发布PTZ主题[%s]失败:%s", topic, err.Error()), nil)
- return
- }
- }
- o.Response(Success, "成功", nil)
- }
- // Snapshot @Title 抓图上报
- // @Description 摄像头抓图上报
- // @router /v1/snapshot [post]
- func (o *CameraController) Snapshot() {
- f, fh, err := o.Ctx.Request.FormFile("file")
- if err != nil {
- return
- }
- defer f.Close()
- f.Seek(0, 0)
- content, err := ioutil.ReadAll(f)
- if err != nil {
- return
- }
- strDate := util.MlNow().Format("2006-01-02")
- filepath := "file" + string(os.PathSeparator) + "snapshot" + string(os.PathSeparator)
- strList := strings.Split(fh.Filename, "_")
- if len(strList) >= 2 {
- filepath = filepath + strList[0] + string(os.PathSeparator)
- strList2 := strings.Split(strList[1], ".")
- if len(strList2) > 0 {
- i64, err := strconv.ParseInt(strList2[0], 10, 64)
- if err == nil {
- strDate = time.Unix(i64, 0).Format("2006-01-02")
- }
- }
- }
- filepath = filepath + strDate + string(os.PathSeparator)
- os.MkdirAll(filepath, os.ModePerm)
- filepath = filepath + fh.Filename
- err = ioutil.WriteFile(filepath, content, os.ModePerm)
- if err != nil {
- beego.Error("Snapshot存储抓图发生错误:", err)
- }
- }
- // PresetPicture @Title 预置位图片上传
- // @Description 预置位图片上传
- // @router /v1/preset/picture [post]
- func (o *CameraController) PresetPicture() {
- f, fh, err := o.Ctx.Request.FormFile("file")
- if err != nil {
- return
- }
- defer f.Close()
- f.Seek(0, 0)
- content, err := ioutil.ReadAll(f)
- if err != nil {
- return
- }
- filepath := "file" + string(os.PathSeparator) + "preset" + string(os.PathSeparator)
- os.MkdirAll(filepath, os.ModePerm)
- filepath = filepath + fh.Filename
- err = ioutil.WriteFile(filepath, content, os.ModePerm)
- if err != nil {
- beego.Error("Snapshot存储抓图发生错误:", err)
- }
- }
- // FLV @Title 上传MP4
- // @Description 上传MP4
- // @router /v1/flv [post]
- func (o *CameraController) FLV() {
- f, fh, err := o.Ctx.Request.FormFile("file")
- if err != nil {
- return
- }
- defer f.Close()
- f.Seek(0, 0)
- content, err := ioutil.ReadAll(f)
- if err != nil {
- return
- }
- strDate := util.MlNow().Format("2006-01-02")
- filepath := "file" + string(os.PathSeparator) + "flv" + string(os.PathSeparator)
- strList := strings.Split(fh.Filename, "_")
- if len(strList) >= 2 {
- filepath = filepath + strList[0] + string(os.PathSeparator)
- strList2 := strings.Split(strList[1], ".")
- if len(strList2) > 0 {
- i64, err := strconv.ParseInt(strList2[0], 10, 64)
- if err == nil {
- strDate = time.Unix(i64, 0).Format("2006-01-02")
- }
- }
- }
- filepath = filepath + strDate + string(os.PathSeparator)
- os.MkdirAll(filepath, os.ModePerm)
- filepath = filepath + fh.Filename
- err = ioutil.WriteFile(filepath, content, os.ModePerm)
- if err != nil {
- beego.Error("MP4存储发生错误:", err)
- }
- }
- // GetSnapshot @Title 获取抓取的图片
- // @Description 获取抓取的图片
- // @router /v1/select/snapshot [get]
- func (o *CameraController) GetSnapshot() {
- code := o.GetString("code") //设备编号
- date := o.GetString("date") //
- if code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- if date == "" {
- date = util.MlNow().Format("2006-01-02")
- }
- //dir := "file/snapshot/" + util.MlNow().Format("2006-01-02") + "/"
- filepath := "file" + string(os.PathSeparator) + "snapshot" + string(os.PathSeparator) +
- code + string(os.PathSeparator) + date + string(os.PathSeparator)
- fis, err := ioutil.ReadDir(filepath)
- if err != nil {
- beego.Error(fmt.Sprintf("未找到该路径[%s],请先抓图", err.Error()))
- o.Response(Failure, "未找到该路径,请先抓图", nil)
- return
- }
- var obj RespSnapshotUrl
- obj.Code = code
- obj.Date = date
- for _, v := range fis {
- if strings.HasSuffix(v.Name(), ".jpg") { //只返回jpg图片
- jpgUrl := BaseUrl + "/file/snapshot/" + code + "/" + date + "/" + v.Name()
- obj.URLs = append(obj.URLs, jpgUrl)
- }
- }
- o.Response(Success, "成功", obj)
- }
- // GetFLV @Title 获取录制的视频
- // @Description 获取录制的视频
- // @router /v1/select/flv [get]
- func (o *CameraController) GetFLV() {
- code := o.GetString("code") //设备编号
- date := o.GetString("date") //
- if code == "" {
- beego.Error(fmt.Sprintf("请输入正确的参数"))
- o.Response(Failure, "参数错误", nil)
- return
- }
- if date == "" {
- date = util.MlNow().Format("2006-01-02")
- }
- //dir := "file/snapshot/" + util.MlNow().Format("2006-01-02") + "/"
- filepath := "file" + string(os.PathSeparator) + "flv" + string(os.PathSeparator) +
- code + string(os.PathSeparator) + date + string(os.PathSeparator)
- fis, err := ioutil.ReadDir(filepath)
- if err != nil {
- beego.Error(fmt.Sprintf("未找到该路径[%s],请先录制mp4", err.Error()))
- o.Response(Failure, "未找到该路径,请先录制mp4", nil)
- return
- }
- var obj RespSnapshotUrl
- obj.Code = code
- obj.Date = date
- for _, v := range fis {
- if strings.HasSuffix(v.Name(), ".mp4") { //只返回jpg图片
- jpgUrl := BaseUrl + "/file/mp4/" + code + "/" + date + "/" + v.Name()
- obj.URLs = append(obj.URLs, jpgUrl)
- }
- }
- o.Response(Success, "成功", obj)
- }
|