【硅谷课堂】腾讯云点播WEB上传方式代码(第二种方式)

下载依赖 npm i vod-js-sdk-v6

前端

/vod/course/Video/Form.vue

<template>
  <!-- 添加和修改课时表单 -->
  <el-dialog :visible="dialogVisible" title="添加课时" @close="close()">
    <el-form :model="video" label-width="120px">
      <el-form-item label="课时标题">
        <el-input v-model="video.title"/>
      </el-form-item>
      <el-form-item label="课时排序">
        <el-input-number v-model="video.sort" :min="0" />
      </el-form-item>
      <el-form-item label="是否免费">
        <el-radio-group v-model="video.isFree">
          <el-radio :label="0">免费</el-radio>
          <el-radio :label="1">默认</el-radio>
        </el-radio-group>
      </el-form-item>
      <!-- 上传视频 -->
      <el-form-item label="上传视频">
      <el-upload
    class="upload-demo"
    ref="upload"
    action="#"
    :http-request="uploadVideo" 
    :limit="1" 
    :on-remove="handleRemove" 
    :on-change="handleChange" 
    :auto-upload="false">
        <el-button slot="trigger" size="small" type="primary">选取视频</el-button>
        <el-button style="margin-left: 40px;" size="small" type="success" @click="submitUpload">点击上传</el-button>
        <el-progress class="progress" :text-inside="true" :stroke-width="18" :percentage="progress" status="exception"></el-progress>
      <div slot="tip" class="el-upload__tip">只能上传mp4文件,且不超过500M</div>
    </el-upload>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="close()">取 消</el-button>
      <el-button type="primary" @click="saveOrUpdate()">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import videoApi from '@/api/vod/video'
import TcVod from 'vod-js-sdk-v6'
import request from '@/utils/request'
export default {
  data() {
    return {
      BASE_API: 'http://localhost:8301',
      dialogVisible: false,
      video: {
        sort: 0,
        free: false
      },
      fileList: [], // 上传文件列表
      uploadBtnDisabled: false,
      // 进度条百分比
      progress: 0,
      //图片原名称
      filename:"",
      fileId:"",
      // 上传成功后的地址
      videoURL: '',
    }
  },
  methods: {
    open(chapterId, videoId) {
      this.dialogVisible = true
      this.video.chapterId = chapterId
      if (videoId) {
        videoApi.getById(videoId).then(response => {
          this.video = response.data
          // 回显
          if (this.video.videoOriginalName) {
            this.fileList = [{ 'name': this.video.videoOriginalName }]
          }
        })
      }
    },
    close() {
      this.dialogVisible = false
      // 重置表单
      this.resetForm()
    },
    resetForm() {
      this.video = {
        sort: 0,
        free: false
      }
      this.fileList = [] // 重置视频上传列表
    },
    saveOrUpdate() {
      if (!this.video.id) {
        this.save()
      } else {
        this.update()
      }
    },
    save() {
      this.video.courseId = this.$parent.$parent.courseId
      videoApi.save(this.video).then(response => {
        this.$message.success(response.message)
        // 关闭组件
        this.close()
        // 刷新列表
        this.$parent.fetchNodeList()
      })
    },
    update() {
      videoApi.updateById(this.video).then(response => {
        this.$message.success(response.message)
        // 关闭组件
        this.close()
        // 刷新列表
        this.$parent.fetchNodeList()
      })
    },
    // 上传多于一个视频
    handleUploadExceed(files, fileList) {
      this.$message.warning('想要重新上传视频,请先删除已上传的视频')
    },
    // 获取签名  这里的签名请求是由后端提供的,只需要拿到后端给的签名请求即可
    getVodSignature () {
      const url = this.BASE_API+'/admin/vod/sign'
      return request.get(url).then(function (response) {
        return response.data
      })
    },
    // 文件列表改变时  将文件列表保存到本地
    handleChange (file, fileList) {
      this.fileList = fileList
      this.filename = this.fileList[0].raw.name
    },
    // 上传
    submitUpload() {
      if (this.fileList.length < 1) return this.$message.warning('请先选取视频,再进行上传')
      this.uploadVideo()
     },
     // 自定义上传
    uploadVideo (e) {
      // 当
      console.log(this.fileList[0].raw)
      if (this.fileList.length < 1) {
        window.alert('您还没有选取文件')
      } else {
          //必须以函数的形式返回  sdk参数限制
        const getSignature = async () => {
          const data = await this.getVodSignature()
          return data
        }
        const tcVod = new TcVod({
          getSignature: getSignature // 获取上传签名的函数
        })
        // 获取通过elementui上传到本地的文件  因为参数类型必须为file 不能直接以对象的形式传输
        const mediaFile = this.fileList[0].raw
        const uploader = tcVod.upload({
          mediaFile: mediaFile
        })
        // 监听上传进度
        uploader.on('media_progress', info => {
          this.progress = parseInt(info.percent * 100)
        })
        // 上传结束时,将url存到本地
        uploader.done().then(doneResult => {
          // 保存地址
          // console.log(doneResult)
          // console.log(this.fileId)
          this.video.videoSourceId = doneResult.fileId
          this.video.videoOriginalName = this.filename;
          // 将视频的第一帧保存为封面  不需要封面的可以直接忽略掉以下代码
          const canvas = document.createElement('canvas')
          const img = document.getElementById('video_img')
          const video = document.getElementById('video')
          video.setAttribute('crossOrigin', 'anonymous')
          canvas.width = video.clientWidth
          canvas.height = video.clientHeight
          video.onloadeddata = (res) => {
            canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)
            const dataURL = canvas.toDataURL('image/png')
            img.setAttribute('src', dataURL)
            // 拿到base64的字符串,并保存到本地
            this.imgBase = dataURL.split(',')[1]
          }
        })
      }
    },
    // 点击删除时
    handleRemove (file, fileList) {
      console.log(file, fileList.length)
    }
    },
}
</script>

/api/video.js

import request from '@/utils/request'

const api_name = '/admin/vod/video'

export default {

  save(video) {
    return request({
      url: `${api_name}/save`,
      method: 'post',
      data: video
    })
  },

  getById(id) {
    return request({
      url: `${api_name}/get/${id}`,
      method: 'get'
    })
  },

  updateById(video) {
    return request({
      url: `${api_name}/update`,
      method: 'put',
      data: video
    })
  },

  removeById(id) {
    return request({
      url: `${api_name}/remove/${id}`,
      method: 'delete'
    })
  }
}

后端

service-vod模块

TencentCloudVodController === (VodController)

package com.atguigu.ggkt.vod.controller;

import com.atguigu.ggkt.exception.GgktException;
import com.atguigu.ggkt.result.Result;
import com.atguigu.ggkt.vod.service.TencentCloudVodService;
import com.atguigu.ggkt.vod.utils.ConstantPropertiesUtil;
import com.atguigu.ggkt.vod.utils.Signature;
import com.baomidou.mybatisplus.extension.api.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

/**
 * @Created with IntelliJ IDEA.
 * @author:YanHui
 * @date: 2023/01/05/19:31
 * @msg:
 */
@Api(tags = "腾讯云点播")
@RestController
@RequestMapping("/admin/vod")
@CrossOrigin
public class TencentCloudVodController {

    @ApiOperation("获取签名")
    @GetMapping("sign")
    public Result sign() {
        Signature sign = new Signature();
        // 设置 App 的云 API 密钥
        sign.setSecretId(ConstantPropertiesUtil.ACCESS_KEY_ID);
        sign.setSecretKey(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
        sign.setCurrentTime(System.currentTimeMillis() / 1000);
        sign.setRandom(new Random().nextInt(java.lang.Integer.MAX_VALUE));
        sign.setSignValidDuration(3600 * 24 * 2); // 签名有效期:2天
        try {
            String signature = sign.getUploadSignature();
            System.out.println("signature : " + signature);
            return Result.ok(signature);
        } catch (Exception e) {
            System.out.print("获取签名失败");
            e.printStackTrace();
            throw new GgktException(20001, "获取签名失败");
        }
    }
}

VideoController

package com.atguigu.ggkt.vod.controller;


import com.atguigu.ggkt.model.vod.Video;
import com.atguigu.ggkt.result.Result;
import com.atguigu.ggkt.vod.service.VideoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * <p>
 * 课程视频 前端控制器
 * </p>
 *
 * @author YanHui
 * @since 2023-01-03
 */
@Api(tags = "课程小结(课时)")
@RestController
@RequestMapping(value="/admin/vod/video")
@CrossOrigin
public class VideoController {
    @Resource
    private VideoService videoService;

    @ApiOperation(value = "获取")
    @GetMapping("get/{id}")
    public Result get(@PathVariable Long id) {
        Video video = videoService.getById(id);
        return Result.ok(video);
    }

    @ApiOperation(value = "新增")
    @PostMapping("save")
    public Result save(@RequestBody Video video) {
        videoService.save(video);
        return Result.ok(null);
    }

    @ApiOperation(value = "修改")
    @PutMapping("update")
    public Result updateById(@RequestBody Video video) {
        videoService.updateVideoById(video);
        return Result.ok(null);
    }

    @ApiOperation(value = "删除")
    @DeleteMapping("remove/{id}")
    public Result remove(@PathVariable Long id) {
        videoService.removeVideoById(id);
        return Result.ok(null);
    }
}

VideoService

package com.atguigu.ggkt.vod.service;

import com.atguigu.ggkt.model.vod.Video;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 课程视频 服务类
 * </p>
 *
 * @author YanHui
 * @since 2023-01-03
 */
public interface VideoService extends IService<Video> {

    /**
     * 根据课程id删除小节
     * @param id
     */
    void removeByCourseId(Long id);

    /**
     * 根据id删除小节
     * @param id
     */
    void removeVideoById(Long id);

    /**
     * 根据id修改小节
     * @param video
     */
    void updateVideoById(Video video);
}

VideoServiceImpl

package com.atguigu.ggkt.vod.service.impl;

import com.atguigu.ggkt.model.vod.Video;
import com.atguigu.ggkt.vod.mapper.VideoMapper;
import com.atguigu.ggkt.vod.service.TencentCloudVodService;
import com.atguigu.ggkt.vod.service.VideoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 课程视频 服务实现类
 * </p>
 *
 * @author YanHui
 * @since 2023-01-03
 */
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {
    @Resource
    private TencentCloudVodService tencentCloudVodService;

    @Override
    public void removeByCourseId(Long id) {
        LambdaQueryWrapper<Video> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Video::getCourseId,id);
        List<Video> videoList = this.list(wrapper);
        for (Video video : videoList) {
            String videoSourceId = video.getVideoSourceId();
            //如果视频id不为空,调用方法删除
            if(!StringUtils.isEmpty(videoSourceId)) {
                tencentCloudVodService.removeTencentCloudVideo(videoSourceId);
            }
        }
        this.remove(wrapper);
    }

    @Override
    public void removeVideoById(Long id) {
        Video video = this.getById(id);
        String videoSourceId = video.getVideoSourceId();
        tencentCloudVodService.removeTencentCloudVideo(videoSourceId);
        this.removeById(video);
    }

    @Override
    public void updateVideoById(Video video) {
        Video oldVideo = this.getById(video.getId());
        //如果新的文件id与旧的不相等
        if(oldVideo.getVideoSourceId()!=null && !oldVideo.getVideoSourceId().equals(video.getVideoSourceId())){
            //先删除旧视频
            tencentCloudVodService.removeTencentCloudVideo(oldVideo.getVideoSourceId());
        }
        this.updateById(video);
    }
}

TencentCloudVodService

package com.atguigu.ggkt.vod.service;

import java.io.InputStream;

/**
 * @Created with IntelliJ IDEA.
 * @author:YanHui
 * @date: 2023/01/05/19:33
 * @msg:
 */
public interface TencentCloudVodService {
    /**
     * 删除云点播视频
     * @param fileId
     */
    void removeTencentCloudVideo(String fileId);
}

TencentCloudVodServiceImpl

package com.atguigu.ggkt.vod.service.impl;

import com.atguigu.ggkt.exception.GgktException;
import com.atguigu.ggkt.vod.service.TencentCloudVodService;
import com.atguigu.ggkt.vod.utils.ConstantPropertiesUtil;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.DeleteMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.DeleteMediaResponse;
import org.springframework.stereotype.Service;

import java.io.InputStream;

/**
 * @Created with IntelliJ IDEA.
 * @author:YanHui
 * @date: 2023/01/05/19:36
 * @msg:
 */
@Service
public class TencentCloudVodServiceImpl implements TencentCloudVodService {

    @Override
    public void removeTencentCloudVideo(String fileId) {
        try{
            // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(ConstantPropertiesUtil.ACCESS_KEY_ID
                    , ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            // 实例化一个http选项,可选的,没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("vod.tencentcloudapi.com");
            // 实例化一个client选项,可选的,没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            VodClient client = new VodClient(cred, "", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DeleteMediaRequest req = new DeleteMediaRequest();
            req.setFileId(fileId);
            // 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应
            DeleteMediaResponse resp = client.DeleteMedia(req);
            // 输出json格式的字符串回包
            System.out.println(DeleteMediaResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            throw new GgktException(20001,e.getMessage());
        }
    }
}
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值