Day208.【课程列表功能】、阿里云视频点播、使用服务端SDK、Java上传SDK、项目整合上传微服务功能、删除阿里云视频 -谷粒学院

谷粒学院

【课程列表】功能

一、课程列表分页显示

参考讲师列表部分快速完成

1、后端部分

  • EduCourseController
    //课程列表 基本实现
    @GetMapping("/getCourseList")
    public R getCourseList(){
    
    
        List<EduCourse> list = eduCourseService.list(null);
        return R.ok().data("list",list);
    }

    //多条件查询课程带分页
    @ApiOperation(value = "多条件查询课程带分页")
    @PostMapping("/pageCourseCondition/{page}/{limit}")
    public R pageCourseCondition(@ApiParam(name = "page", value = "当前页码", required = true)@PathVariable Long page,
                                  @ApiParam(name = "limit", value = "每页记录数", required = true)@PathVariable Long limit,
                                 @RequestBody(required = false) CourseQuery courseQuery){
    
    //通过封装courseQuery对象来直接传递查询条件
        //创建分页page对象
        Page<EduCourse> pageParam = new Page<>(page, limit);

        //调用方法实现多条件分页查询
        eduCourseService.pageQuery(pageParam,courseQuery);

        //获取查询到的数据
        List<EduCourse> records = pageParam.getRecords();

        //获取总记录数
        long total = pageParam.getTotal();
        return R.ok().data("total",total).data("rows",records);
    }
  • EduCourseService
//多条件查询讲师带分页
void pageQuery(Page<EduCourse> pageParam, CourseQuery courseQuery);
  • EduCourseServiceImpl
@Override
public void pageQuery(Page<EduCourse> pageParam, CourseQuery courseQuery) {
    
    

    //构建条件
    QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();

    //取出值,判断他们是否有值
    String title = courseQuery.getTitle();
    String status = courseQuery.getStatus();

    //判断条件值是否为空,如果不为空,拼接条件
    //判断是否有传入教师名
    if (!StringUtils.isEmpty(title)) {
    
    
        //构建条件
        wrapper.like("title", title);//参数1:数据库字段名; 参数2:模糊查询的值
    }
    //判断是否传入状态
    if (!StringUtils.isEmpty(status)) {
    
    
        //构造条件
        wrapper.eq("status", status);
    }

    //排序
    wrapper.orderByDesc("gmt_create");

    //带上门判断后的条件进行分页查询
    baseMapper.selectPage(pageParam, wrapper);
}
  • com.achang.eduservice.entity.vo.CourseQuery
@ApiModel(value = "Course查询对象", description = "课程查询对象封装")
@Data
public class CourseQuery implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "课程名称,模糊查询")
    private String title;

    @ApiModelProperty(value = "发布状态 Normal已发布 Draft未发布")
    private String status;

}

2、前端部分

  • api方法
    //课程列表多条件分页查询
    //page:当前页,limit:每页记录数,teacherQuery:条件对象
    getCourseListPage(page, limit, courseQuery) {
    
    
        return request({
    
    
            url: `/eduservice/edu-course/pageCourseCondition/${
      
      page}/${
      
      limit}`,
            method: 'post',
            //teacherQuery条件对象,如果后端使用RequestBody获取数据
            //data表示把对象转换成json对象进行传递到接口里
            data: courseQuery
        })
    },

    //课程列表数据查询
    getCourseList() {
    
    
        return request({
    
    
            url: "/eduservice/edu-course/getCourseList/",
            method: 'get',
        })
    }
  • 导入api方法
//引入要调用的方法,teacher.js文件
import course from "@/api/teacher/course.js";
  • 页面列表页面模版
    <!--数据显示的表格-->
    <el-table
      :data="list"
      style="width: 100%"
      border
      fit
      highlight-current-row
      element-loading-text="数据加载中"
    >
      <el-table-column prop="date" label="序号" width="70" align="center">
        <template slot-scope="scope">
          {
   
   { (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>
      <el-table-column prop="title" label="课程名称" width="80">
      </el-table-column>
      <el-table-column label="发布状态" width="80">
        <template slot-scope="scope">
          {
   
   { scope.row.status === "Normal" ? "已发布" : "未发布" }}
        </template>
      </el-table-column>
      <el-table-column prop="lessonNum" label="课时数" width="200" />
      <el-table-column prop="gmtCreate" label="添加时间" width="300" />
      <el-table-column prop="viewCount" label="浏览数量" width="500" />
      <el-table-column label="操作" align="center">
        <template slot-scope="scope">
          <router-link :to="'/teacher/edit/' + scope.row.id">
            <el-button type="primary" size="mini" icon="el-icon-edit"
              >编辑课程基本信息</el-button
            >
          </router-link>
          <router-link :to="'/teacher/edit/' + scope.row.id">
            <el-button type="info" size="mini" icon="el-icon-edit"
              >编辑课程大纲</el-button
            >
          </router-link>
          <el-button
            type="danger"
            size="mini"
            icon="el-icon-delete"
            @click="removeById(scope.row.id)"
            >课程删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <!--分页组件-->
    <el-pagination
      background
      layout="prev, pager, next,total,jumper"
      :total="total"
      :page-size="limit"
      style="padding: 30px 0; text-align: center"
      :current-page="page"
      @current-change="getList"
    >
    </el-pagination>
  • js代码
export default {
    
    
  //写核心代码位置
  data() {
    
    
    //1、定义变量和初始值
    return {
    
    
      list: null, //查询之后给接口返回的数据装的集合
      page: 1, //当前页
      limit: 10, //每页显示记录数
      courseQuery: {
    
    }, //条件封装对象
      total: 0, //总记录数
    };
  },
  created() {
    
    
    //页面渲染之前执行,调用method定义的方法
    //调用
    this.getList();
  },
  methods: {
    
    
    //调用具体的方法,调用teacher.js定义的方法
    //课程列表的方法
    getList(page = 1) {
    
    
      this.page = page;
      course
        .getCourseListPage(this.page, this.limit, this.courseQuery)
        .then((resp) => {
    
    
          //resp接口返回的数据
          this.list = resp.data.rows;
          this.total = resp.data.total;
        }) //请求成功
        .catch((err) => {
    
    
          console.log(err);
        }); //请求失败
    },
    //清空方法
    resetData() {
    
    
      //表单输入项数据清空
      this.courseQuery = {
    
    };
      //查询所有课程数据
      this.getList();
    },
  },
};
</script>
  • 效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1O0vUEiL-1614694435627)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302143401575.png)]

二、课程列表中的课程删除

1、后端部分

编写后端接口

  • EduCourseController
    //课程列表中删除课程方法
    @DeleteMapping("/removeCourseById/{id}")
    public R removeCourseById(@PathVariable String id){
    
    
        boolean flag = eduCourseService.removeCourse(id);
        if (flag){
    
    
            return R.ok();
        }else {
    
    
            return R.error();
        }
    }
  • EduCourseService
//删除课程
boolean removeCourse(String id);
  • EduVideoServiceImpl
@Service
public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {
    
    

    //根据课程id删除小节
    // TODO 删除小节,要删除对应的视频文件
    @Override
    public void removeVideoByCourseId(String id) {
    
    
        QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",id);
        baseMapper.delete(wrapper);
    }
}
  • EduChapterService
void removeChapterByCourseId(String id);
  • EduChapterServiceImpl
@Override
public void removeChapterByCourseId(String id) {
    
    
    QueryWrapper<EduChapter> wrapper = new QueryWrapper<>();
    wrapper.eq("course_id",id);
    baseMapper.delete(wrapper);
}
  • EduCourseServiceImpl
    //删除课程
    @Override
    public boolean removeCourse(String id) {
    
    
        //1、根据课程id删除小节
        eduVideoService.removeVideoByCourseId(id);

        //2、根据课程id删除章节部分
        eduChapterService.removeChapterByCourseId(id);

        //3、根据课程id删除课程描述
        eduCourseDescriptionService.removeById(id);

        //4、根据课程id删除课程本身
        int result = baseMapper.deleteById(id);

        if (result>=1){
    
    
            return true;
        }else {
    
    
            throw new AchangException(20001,"删除失败");
        }

    }
  • 测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3VNhBqB-1614694435630)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302153940227.png)]

  • 查看数据库

课程id为101的全部都删除了


2、前端部分

  • 编写api方法

guli-admin\src\api\teacher\course.js

    //课程列表数据查询
    removeCourseById(courseId){
    
    
        return request({
    
    
            url: "/eduservice/edu-course/removeCourseById/"+courseId,
            method: 'get',
        })
    }
  • 引入api

guli-admin\src\views\edu\course\list.vue

//引入要调用的方法,course.js文件
import course from "@/api/teacher/course.js";
  • 调用方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ZqvLvZj-1614694435632)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302144732554.png)]

    removeCourseById(id) {
    
    
      this.$confirm("此操作将永久删除该课程记录, 是否继续?", "提示", {
    
    
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
    
    
        //点击确定,执行then方法
        course.removeCourseById(id).then((resp) => {
    
    
          //删除成功
          //提示信息
          this.$message({
    
    
            type: "success",
            message: "删除成功!",
          });
          //刷新页面
          this.getList();
        });
      });
    }
  • 效果测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ovhWYZvV-1614694435635)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302144845922.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PV7biNPu-1614694435637)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302144852706.png)]


  • 前端导航栏
    <!--多条件查询表单-->
    <el-form
      :inline="true"
      class="demo-form-inline"
      style="margin-left: 20px; margin-top: 12px"
    >
      <el-form-item label="课程名称">
        <el-input
          v-model="courseQuery. "
          placeholder="请输入名称"
        ></el-input>
      </el-form-item>
      <el-form-item label="发布状态">
        <el-select v-model="courseQuery.status" placeholder="课程状态">
          <el-option label="已发布" :value="'Normal'"></el-option>
          <el-option label="未发布" :value="'Draft'"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="getList()"
          >查询</el-button
        >
        <el-button type="default" @click="resetData()">清空</el-button>
      </el-form-item>
    </el-form>
  • 效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAy3cxmW-1614694435638)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302154235228.png)]


三、课程列表中的编辑课程基本信息、编辑课程大纲功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yBfsstqj-1614694435639)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302154705981.png)]

  • 前端
<router-link :to="'/course/info/' + scope.row.id">
    <el-button type="primary" size="mini" icon="el-icon-edit"
               >编辑课程基本信息</el-button
        >
</router-link>
<router-link :to="'/course/chapter/' + scope.row.id">
    <el-button type="info" size="mini" icon="el-icon-edit"
               >编辑课程大纲</el-button
        >
</router-link>
  • 修改路由

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5nOTdrsA-1614694435641)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302154759229.png)]

  • guli-admin\src\views\edu\course\chapter.vue

根据连接中是否有id值来决定是否回显数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZZjzUaOB-1614694435642)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302154833090.png)]

  • guli-admin\src\views\edu\course\info.vue

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PWzpyMOm-1614694435643)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302154904748.png)]


阿里云视频点播

一、介绍

参考文章:

https://blog.csdn.net/qq_33857573/article/details/79564255


视频点播( ApsaraVideo for VoD )是集音视频采集、编辑、上传、自动化转码处理、媒体资源管理、分
发加速于一体的一站式音视频点播解决方案。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0s7QbAnD-1614694435645)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302155416142.png)]

二、开通视频点播云平台

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hA3CS0ed-1614694435646)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302155221331.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xO6UQJE0-1614694435648)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302155340566.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q71we98w-1614694435649)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302155435503.png)]

资费说明

https://www.aliyun.com/price/product?spm=a2c4g.11186623.2.12.7fbd59b9vmXVN6#/vod/detail

  • 后付费
  • 套餐包
  • 欠费说明
  • 计费案例:https://help.aliyun.com/document_detail/64032.html?spm=a2c4g.11186623.4.3.363db1bcfdvxB5

三、整体流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KngkoHs5-1614694435650)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162750808.png)]

四、视频点播服务的基本使用

完整的参考文档:

https://help.aliyun.com/product/29932.html?spm=a2c4g.11186623.6.540.3c356a58OEmVZJ

1 、设置转码格式

选择全局设置 > 转码设置,单击添加转码模板组。

在视频转码模板组页面,根据业务需求选择封装格式和清晰度。

或直接将已有的模板设置为默认即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cS07t37u-1614694435651)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162846420.png)]

2 、分类管理

选择全局设置 > 分类管理

3 、上传视频文件

选择媒资库 > 音视频,单击上传音视频

4 、配置域名

音视频上传完成后,必须配一个已备案的域名,并完成 CNAME 绑定

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eguH7wV2-1614694435653)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162908488.png)]

得到 CNAME

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9VKmtWZ-1614694435654)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162916995.png)]

在购买域名的服务商处的管理控制台配置域名解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoMvgZ3N-1614694435655)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162925490.png)]

5 、在控制台查看视频

此时视频可以在阿里云控制台播放

6 、获取 web 播放器代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UjauKSF3-1614694435656)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302162952462.png)]


使用服务端SDK

一、服务端SDK

1、简介

sdk的方式将api进行了进一步的封装,不用自己创建工具类。

我们可以基于服务端SDK编写代码来调用点播API,实现对点播产品和服务的快速操作

2、功能介绍

  • SDK封装了对API的调用请求和响应,避免自行计算较为繁琐的 API签名。

  • 支持所有点播服务的API,并提供了相应的示例代码。

  • 支持7种开发语言,包括:Java、Python、PHP、.NET、Node.js、Go、C/C++。

  • 通常在发布新的API后,我们会及时同步更新SDK,所以即便您没有找到对应API的示例代码,也可以参考旧的示例自行实现调用。


二、使用SDK

0、创建环境

  • 在service下创建子模块service_vod引入下面相关依赖,因为在父工程guli_parent已经规定了版本号
    <dependencies>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-vod</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
    </dependencies>

1、安装

参考文档:https://help.aliyun.com/document_detail/57756.html

添加maven仓库的配置和依赖到pom

<repositories>
    <repository>
        <id>sonatype-nexus-staging</id>
        <name>Sonatype Nexus Staging</name>
        <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

添加Jar包依赖

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.1</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-vod</artifactId>
    <version>2.15.11</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>
  • aliyun-java-sdk-core的版本4.4.5及以上。
  • aliyun-java-sdk-vod的版本,请参见服务端SDK发布历史,首段的Version即为最新的版本号。

2、初始化

参考文档:https://help.aliyun.com/document_detail/61062.html
根据文档示例创建 com.achang.vodtest.InitObject

//初始化类
public class InitObject {
    
    

    public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
    
    
        String regionId = "cn-shanghai";  // 点播服务接入区域
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        return client;
    }

}

3、测试功能

获取视频播放地址:

    public static void main(String[] args) throws ClientException {
    
    
        //1、根据视频id获取视频播放地址
        //创建初始化对象
        DefaultAcsClient cl = InitObject.initVodClient("LTAI4GBABS7Sq8MLf2RNwLuu", "ynfsD31FLdcRoQVFSIdHP7AeoKaf4o");
        //创建获取视频地址request对象和response对象
        GetPlayInfoResponse response = new GetPlayInfoResponse();
        GetPlayInfoRequest request = new GetPlayInfoRequest();
        //向request对象设置视频id值
        request.setVideoId("e9102d65ba3649f0b9fc8679cc5bda42");


        //调用初始化对象里面的方法传递request,获取数据
        response = cl.getAcsResponse(request);
        List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();
        //播放地址
        for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) {
    
    
            System.out.print("PlayInfo.PlayURL = " + playInfo.getPlayURL() + "\n");
            //PlayInfo.PlayURL = https://outin-5e688ec47b2c11ebb00500163e06123c.oss-cn-shanghai.aliyuncs.com/sv/52a57879-177f1fd5033/52a57879-177f1fd5033.mp4?Expires=1614680252&OSSAccessKeyId=LTAIrkwb21KyGjJl&Signature=FPlVfGbIDVGuvR3W8f2K4QcpATw%3D
        }
        //Base信息
        System.out.print("VideoBase.Title = " + response.getVideoBase().getTitle() + "\n");//VideoBase.Title = 6 - What If I Want to Move Faster.mp4
    }

获取视频播放凭证:

@Test
public void test1() throws ClientException {
    
    
    //创建初始化对象
    DefaultAcsClient cl = InitObject.initVodClient("LTAI4GBABS7Sq8MLf2RNwLuu", "ynfsD31FLdcRoQVFSIdHP7AeoKaf4o");
    //创建获取视频地址request对象和response对象
    GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
    //向request对象设置视频id值
    request.setVideoId("e9102d65ba3649f0b9fc8679cc5bda42");

    GetVideoPlayAuthResponse response = cl.getAcsResponse(request);

    //播放凭证
    System.out.print("PlayAuth = " + response.getPlayAuth() + "\n");
    //VideoMeta信息
    System.out.print("VideoMeta.Title = " + response.getVideoMeta().getTitle() + "\n");

}

使用服务端SDK

参考文档:https://help.aliyun.com/document_detail/53406.html

一、安装SDK

1、配置pom

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.1</version>
</dependency>
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-vod</artifactId>
    <version>2.15.11</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.28</version>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20170516</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
</dependency>

2、安装非开源jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtdfE1Zo-1614694435658)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302175354235.png)]

在本地Maven仓库中安装jar包:

下载视频上传SDK,解压,命令行进入lib目录,执行以下代码

mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.11 -Dpackaging=jar -Dfile=aliyun-java-vod-upload-1.4.11.jar

然后在pom中引入jar包

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-sdk-vod-upload</artifactId>
    <version>1.4.11</version>
</dependency>

二、测试

    @Test
    public void testFileUpload(){
    
    
        String accessKeyId = "LTAI4GBABS7Sq8MLf2RNwLuu";
        String accessKeySecret = "ynfsD31FLdcRoQVFSIdHP7AeoKaf4o";
        String title = "6 - What If I Want to Move Faster"; //上传之后文件的名称
        String fileName = "C:\\Users\\PePe\\Desktop\\学习\\博客\\学习资料\\21、谷粒学院   -尚硅谷\\在线教育--谷粒学院\\1-阿里云上传测试视频\\6 - What If I Want to Move Faster.mp4"; //本地文件的路径和名称

        UploadVideoRequest request = new UploadVideoRequest(accessKeyId, accessKeySecret, title, fileName);
        /* 可指定分片上传时每个分片的大小,默认为2M字节 */
        request.setPartSize(2 * 1024 * 1024L);
        /* 可指定分片上传时的并发线程数,默认为1,(注:该配置会占用服务器CPU资源,需根据服务器情况指定)*/
        request.setTaskNum(1);

        UploadVideoImpl uploader = new UploadVideoImpl();
        UploadVideoResponse response = uploader.uploadVideo(request);
        if (response.isSuccess()) {
    
    
            System.out.print("VideoId=" + response.getVideoId() + "\n"); //获取到上传视频的id
        } else {
    
    
            /* 如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 */
            System.out.print("VideoId=" + response.getVideoId() + "\n");
            System.out.print("ErrorCode=" + response.getCode() + "\n");
            System.out.print("ErrorMessage=" + response.getMessage() + "\n");
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42RTgg0B-1614694435659)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302182820821.png)]


视频点播微服务功能

一、后端部分–【创建视频点播微服务】

1、创建微服务模块

service_vod

2、pom

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-vod</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-sdk-vod-upload</artifactId>
</dependency>
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
</dependency>

3、主启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan(basePackages = {
    
    "com.achang"}) //用于扫描swagger
public class Service_vod_Main8003 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Service_vod_Main8003.class,args);
    }
}

4、VodController

@RestController
@CrossOrigin
@RequestMapping("/eduvod/video")
public class VodController {
    
    

    @Autowired
    private VodService vodService;

    //上传视频到阿里云
    @PostMapping("/uploadAliyunVideo")
    public R  uploadAliyunVideo(MultipartFile file){
    
    
        //返回上传视频的id
        String videoId = vodService.uploadVideoAliyun(file);
        return R.ok().data("videoId",videoId);
    }

}

5、service

  • service接口
public interface VodService {
    
    
    String uploadVideoAliyun(MultipartFile file);
}
  • serviceImpl
@Service
public class VodServiceImpl implements VodService {
    
    
    @Override
    public String uploadVideoAliyun(MultipartFile file) {
    
    

        try {
    
    
            //accessKeyId,accessKeySecret

            //fileName:上传文件原始名称
            String fileName = file.getOriginalFilename();

            //title:上传之后显示名称
            String title = fileName.substring(0,fileName.lastIndexOf("."));

            //inputStream:上传文件的输入流
            InputStream inputStream = file.getInputStream();

            UploadStreamRequest request = new UploadStreamRequest(ConstantVodUtils.ACCESSKEY_ID
                    , ConstantVodUtils.ACCESSKEY_SECRET
                    , title, fileName
                    , inputStream);

            UploadVideoImpl uploader = new UploadVideoImpl();
            UploadStreamResponse response = uploader.uploadStream(request);
            System.out.print("RequestId=" + response.getRequestId() + "\n");  //请求视频点播服务的请求ID
            String videoId = null;
            if (response.isSuccess()) {
    
    
                videoId = response.getVideoId();
            } else {
    
     //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因
                videoId = response.getVideoId();
            }
            return videoId;

        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        }
    }

}

6、ConstantVodUtils

用来读取application.properties里面的值,并封装

@Component
public class ConstantVodUtils implements InitializingBean {
    
    

    @Value("${aliyun.vod.file.keyid}")
    private String accessKeyId;

    @Value("${aliyun.vod.file.keysecret}")
    private String accessKeySecret;

    public static String ACCESSKEY_ID;
    public static String ACCESSKEY_SECRET;


    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        ACCESSKEY_ID = this.accessKeyId;
        ACCESSKEY_SECRET = this.accessKeySecret;
    }
}

7、application.properites

# 服务端口号
server.port=8003

# 服务名
spring.application.name=service_vod

# 环境设置 dev test prod
spring.profiles.active=dev

# 最大上传单个文件大小:默认1M
spring.servlet.multipart.max-file-size=1024MB
# 最大置总上传的数据大小 :默认10M
spring.servlet.multipart.max-request-size=1024MB

# 阿里云 vod
aliyun.vod.file.keyid=LTAI4GBABS7Sq8MLf2RNwLuu
aliyun.vod.file.keysecret=ynfsD31FLdcRoQVFSIdHP7AeoKaf4o

8、测试

通过swagger测试

访问:http://localhost:8003/swagger-ui.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f5WWaxYH-1614694435660)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302202114370.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2vay5lx-1614694435662)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302202138117.png)]


二、前端部分

  • 数据定义
fileList: [], //上传文件列表
BASE_API: process.env.BASE_API, // 接口API地址
  • 整合上传组件
<el-form-item label="上传视频">
    <el-upload
:on-success="handleVodUploadSuccess"
:on-remove="handleVodRemove"
:before-remove="beforeVodRemove"
:on-exceed="handleUploadExceed"
:file-list="fileList"
:action="BASE_API + '/admin/vod/video/upload'"
:limit="1"
class="upload-demo"
>
    <el-button size="small" type="primary">上传视频</el-button>
<el-tooltip placement="right-end">
    <div slot="content">
        最大支持1G,<br />
        支持3GP、ASFAVIDATDVFLVF4V<br />
        GIFM2TM4VMJ2MJPEGMKVMOVMP4<br />
        MPEMPGMPEGMTSOGGQTRMRMVB<br />
        SWFTSVOBWMVWEBM 等视频格式上传
            </div>
<i class="el-icon-question" />
    </el-tooltip>
</el-upload>
</el-form-item>
  • 方法定义
    //上传成功执行方法
    handleVodUploadSuccess(response,file,fileList){
    
    
        this.video.videoSourceId = response.data.videoId
    },
    beforeVodRemove(file, fileList){
    
    
      return this.$confirm(`确定移除 ${
      
       file.name }?`);
    },

三、配置nginx

配置nginx上传文件大小,否则上传时会有 413 (Request Entity Too Large) 异常

打开nginx主配置文件nginx.conf,找到http{},添加

	client_max_body_size 1024m;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vVSmfyVH-1614694435663)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302210840933.png)]

  • 添加转发链接,根据后端端口和接口地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0OOp2s0-1614694435664)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302210954364.png)]

        location ~ /eduvod/ {
				proxy_pass http://localhost:8003;
        }
  • 重启nginx,所在nginx目录
# 关闭nginx
nginx.exe -s -stop

# 启动nginx
nginx.exe

四、测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7TnXv7mR-1614694435666)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302211228373.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7OBY50z-1614694435667)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302211234276.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CL7eNXkN-1614694435668)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302211244387.png)]


删除云端视频

文档:服务端SDK->Java SDK->媒资管理

https://help.aliyun.com/document_detail/61065.html?spm=a2c4g.11186623.6.831.654b3815cIxvma#h2–div-id-deletevideo-div-7


一、后端部分

  • 初始化对象方法

com.achang.voe.Utils.InitObject

//初始化类
public class InitObject {
    
    
    public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
    
    
        String regionId = "cn-shanghai";  // 点播服务接入区域
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        return client;
    }
}
  • com.achang.voe.Utils.ConstantVodUtils
@Component
public class ConstantVodUtils implements InitializingBean {
    
    

    @Value("${aliyun.vod.file.keyid}")
    private String accessKeyId;

    @Value("${aliyun.vod.file.keysecret}")
    private String accessKeySecret;

    public static String ACCESSKEY_ID;
    public static String ACCESSKEY_SECRET;


    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        ACCESSKEY_ID = this.accessKeyId;
        ACCESSKEY_SECRET = this.accessKeySecret;
    }


}
  • controller
    //根据视频id删除阿里云视频
    @DeleteMapping("/removeAliyunVideoById/{id}")
    public R removeAliyunVideoById(@PathVariable String id){
    
    
        vodService.removeAliyunVideoById(id);
        return R.ok();
    }
  • service

接口

void removeAliyunVideoById(String id);

Impl

    //根据id删除阿里云视频
    @Override
    public void removeAliyunVideoById(String id) {
    
    

        try {
    
    
            DefaultAcsClient client = InitObject.initVodClient(ConstantVodUtils.ACCESSKEY_ID, ConstantVodUtils.ACCESSKEY_SECRET);
            DeleteVideoRequest request = new DeleteVideoRequest();
            request.setVideoIds(id);
            DeleteVideoResponse response = client.getAcsResponse(request);
            System.out.println("RequestId = "+ response.getRequestId()+"\n");

        } catch (ClientException e) {
    
    
            throw new AchangException(20001,"视频删除失败");
        }
    }
  • 测试

访问:http://localhost:8003/swagger-ui.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f52E5StX-1614694435669)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302215314655.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NZ2SREn-1614694435671)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302215320362.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IiyBtpFf-1614694435672)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302215347620.png)]


二、前端部分

  • api方法

guli-admin\src\api\teacher\video.js

    //根据视频id删除阿里云视频
    deleteAliyunVideoById(VideoId){
    
    
        return request({
    
    
            url: "/eduvod/video/removeAliyunVideoById/"+VideoId,
            method: 'delete',
        })
    }
  • guli-admin\src\views\edu\course\chapter.vue

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4X80JDe-1614694435673)(../../../../../AppData/Roaming/Typora/typora-user-images/image-20210302215959118.png)]

    handleVodRemove() {
    
    
      //调用接口里面的删除视频方法
      video.deleteAliyunVideoById(this.video.videoSourceId).then((resp) => {
    
    
        this.$message({
    
    
          type: "success",
          message: "删除成功!",
        });
        //把文件列表清空
        this.fileList = [];
        //清空视频id和视频名称
        this.video.videoSourceId =""
        this.video.video_original_name =""
      });
    },

猜你喜欢

转载自blog.csdn.net/qq_43284469/article/details/114296004