1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 最新《谷粒学院开发教程》:5 - 章节管理

最新《谷粒学院开发教程》:5 - 章节管理

时间:2021-07-09 03:20:34

相关推荐

最新《谷粒学院开发教程》:5 - 章节管理

目录

一、课程章节增删改查1.1、后端接口1.2、前端实现1.3、添加章节1.4、修改章节1.5、删除章节二、课程章节小节功能2.1、后端接口2.2、前端实现2.3、添加小节2.4、删除小节2.5、修改小节三、课程发布信息预览3.1、后端接口3.3、前端实现四、课程发布4.1、后端接口4.2、前端页面五、课程列表5.1、后端接口5.2、前端实现六、课程删除6.1、后端接口6.2、前端实现七、编辑基本信息及大纲八、阿里云视频点播8.1、简介8.2、使用九、使用服务端SDK9.1、简介9.2、获取视频9.3、上传视频十、视频点播微服务10.1、后端接口10.2、前端实现10.3、视频删除

一、课程章节增删改查

1.1、后端接口

@Api(tags = "章节模块")@CrossOrigin@RestController@RequestMapping("/eduservice/chapter")public class EduChapterController {@Autowiredprivate EduChapterService eduChapterService;@AutowiredEduCourseService eduCourseService;// 添加章节@PostMapping("addChapter")public R addChapter(@RequestBody EduChapter eduChapter) {eduChapterService.save(eduChapter);return R.ok();}// 根据章节id查询@GetMapping("getChapter/{chapterId}")public R getChapter(@PathVariable String chapterId) {EduChapter eduChapter = eduChapterService.getById(chapterId);return R.ok().data("chapter", eduChapter);}// 修改章节@PostMapping("updateChapter")public R updateChapter(@RequestBody EduChapter eduChapter) {eduChapterService.updateById(eduChapter);return R.ok();}// 删除章节 若存在小节则不可删除@DeleteMapping("deleteById/{chapterId}")public R deleteById(@PathVariable String chapterId) {boolean flag = eduChapterService.deleteChapter(chapterId);if (flag) {return R.ok();} else {return R.error();}}}

@Overridepublic boolean deleteChapter(String chapterId) {QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();wrapper.eq("chapter_id", chapterId);int count = eduVideoService.count(wrapper);if (count > 0) {throw new LaptoyException(20001, "还有小节数据,不能删除");} else {return this.removeById(chapterId);}}

1.2、前端实现

1、页面代码

<template><div class="app-container"><h2 style="text-align: center">发布新课程</h2><!-- 步骤条 --><el-steps :active="2" process-status="wait" align-center style="margin-bottom: 40px;"><el-step title="填写课程基本信息" /><el-step title="创建课程大纲" /><el-step title="最终发布" /></el-steps><!-- 章节数据折叠面板 --><el-collapse accordion v-for="chapter in chapterVideoList" :key="chapter.id"><!-- 按钮组 --><el-button-group><el-button type="primary" size="mini" icon="el-icon-circle-plus">添加小节</el-button><el-button type="primary" size="mini" icon="el-icon-edit" @click="openEditChapter(chapter.id)"></el-button><el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(chapter.id)"></el-button></el-button-group><!-- 小节数据 --><el-collapse-item :title=chapter.title><div v-for="video in chapter.children" :key="video.id">{{ video.title }}<span class="acts"><el-button type="text">编辑</el-button><el-button type="text">删除</el-button></span></div></el-collapse-item></el-collapse><!-- 底部按钮 --><el-form label-width="120px"><el-form-item><el-button @click="dialogChapterFormVisible=true">添加章节</el-button><el-button @click="previous">上一步</el-button><el-button :disabled="saveBtnDisabled" type="primary" @click="next">下 一步</el-button></el-form-item></el-form><!-- 添加或修改章节弹框 --><el-dialog :visible.sync="dialogChapterFormVisible" title="添加章节"><el-form :model="chapter" label-width="120px"><el-form-item label="章节标题"><el-input v-model="chapter.title" /></el-form-item><el-form-item label="章节排序"><el-input-number v-model="chapter.sort" :min="0" controls-position="right" /></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogChapterFormVisible = false">取 消</el-button><el-button type="primary" @click="saveOrUpdate">确 定</el-button></div></el-dialog></div></template>

data() {return {dialogChapterFormVisible: false,chapter: {title: "",sort: 0},};},

稍微优化了页面

2、创建api - chapter.js

//添加章节addChapter(chapter) {return request({url: `/eduservice/chapter/addChapter`,method: `post`,data: chapter})},//根据id查询章节updateChapterById(chapterId) {return request({url: `/eduservice/chapter/getChapter/${chapterId}`,method: `get`,})},//修改章节updateChapter(chapter) {return request({url: `/eduservice/chapter/updateChapter`,method: `post`,data: chapter})},//删除章节deleteById(chapterId) {return request({url: `/eduservice/chapter/deleteById/${chapterId}`,method: `delete`,})}

1.3、添加章节

saveChapter() {//设置课程id到chapter对象中,不指定课程id无法正常保存,因为数据库字段为非空this.chapter.courseId = this.courseIdchapter.addChapter(this.chapter).then((resp) => {this.dialogChapterFormVisible = false;this.$message({message: "添加章节成功",type: "success",});this.chapter = {}this.getChapterVideoByCourseId()});},saveOrUpdate() {this.saveChapter()},

1.4、修改章节

1、点击修改章节按钮根据章节id回显数据

<el-button type="primary" size="mini" icon="el-icon-edit" @click="openEditChapter(chapter.id)"></el-button>

2、修改方法

// 修改章节弹窗回显数据openEditChapter(id) {this.dialogChapterFormVisible = true;chapter.updateChapterById(id).then((resp) => {this.chapter = resp.data.data})},// 修改章节updateChapter(id) {//设置课程id到chapter对象中,不指定课程id无法正常保存,因为数据库字段为非空this.chapter.courseId = this.courseIdchapter.updateChapter(this.chapter).then((resp) => {this.dialogChapterFormVisible = false;this.$message({message: "修改章节成功",type: "success",});this.getChapterVideoByCourseId();});},

1.5、删除章节

<el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(chapter.id)"></el-button>

// 删除章节removeById(chapterId) {this.$confirm("此操作将永久删除章节信息, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {chapter.deleteById(chapterId).then((resp) => {this.$message({type: "success",message: "删除成功!",});this.getChapterVideoByCourseId();});});},

二、课程章节小节功能

2.1、后端接口

@Api(tags = "小节模块")@RestController@RequestMapping("/eduservice/video")@CrossOrigin //解决跨域问题public class EduVideoController {@Autowiredprivate EduVideoService eduVideoService;//添加小节@PostMapping("/addVideo")public R addVideo(@RequestBody EduVideo eduVideo) {eduVideoService.save(eduVideo);return R.ok();}//删除小节// TODO 后面这个方法需要完善,删除小节的时候,同时也要把视频删除@DeleteMapping("/deleteVideo/{id}")public R deleteVideo(@PathVariable String id) {eduVideoService.removeById(id);return R.ok();}//修改小节@PostMapping("/updateVideo")public R updateVideo(@RequestBody EduVideo eduVideo) {eduVideoService.updateById(eduVideo);return R.ok();}//根据小节id查询@GetMapping("/getVideoById/{videoId}")public R getVideoById(@PathVariable String videoId) {EduVideo eduVideo = eduVideoService.getById(videoId);return R.ok().data("data", eduVideo);}}

2.2、前端实现

1、页面

<!-- 章节数据折叠面板 --><el-collapse accordion v-for="chapter in chapterVideoList" :key="chapter.id"><!-- 按钮组 --><el-button-group><el-button type="primary" size="mini" icon="el-icon-circle-plus" @click="openSaveVideoForm(chapter.id)">添加小节</el-button></el-button-group></el-collapse><!--添加小节表单--><el-dialog :visible.sync="dialogVideoFormVisible" title="添加小节"><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" controls-position="right" /></el-form-item><el-form-item label="是否免费"><el-radio-group v-model="video.free"><el-radio :label="true">免费</el-radio><el-radio :label="false">默认</el-radio></el-radio-group></el-form-item><el-form-item label="上传视频"><!-- TODO --></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogVideoFormVisible = false">取 消</el-button><el-button :disabled="saveVideoBtnDisabled" type="primary" @click="saveOrUpdateVideo">确 定</el-button></div></el-dialog>

data() {return {saveVideoBtnDisabled: false,dialogVideoFormVisible: false,video: {sort: 0,title: "",free: ""}};},

2、API - src\api\teacher\video.js

import request from '@/utils/request' //引入已经封装好的axios 和 拦截器export default {//添加小节addVideo(video) {return request({url: `/eduservice/video/addVideo`,method: `post`,data: video})},//根据id查询小节getVideoById(videoId) {return request({url: `/eduservice/video/getVideoById/${videoId}`,method: `get`,})},//修改小节updateVideo(video) {return request({url: `/eduservice/video/updateVideo`,method: `post`,data: video})},//删除小节deleteById(videoId) {return request({url: `/eduservice/video/deleteVideo/${videoId}`,method: `delete`,})},}

2.3、添加小节

openSaveVideoForm(id) {this.dialogVideoFormVisible = truethis.video.courseId = this.courseIdthis.video.chapterId = id},saveOrUpdateVideo(){if (this.video.id) {//修改小节} else {//新增小节this.saveVideo();}},// 添加小节saveVideo() {video.addVideo(this.video).then((resp) => {this.dialogVideoFormVisible = false;this.$message({message: "添加小节成功",type: "success",});this.video = {}this.getChapterVideoByCourseId();});},

2.4、删除小节

<!-- 章节数据折叠面板 --><el-collapse accordion v-for="chapter in chapterVideoList" :key="chapter.id"><!-- 按钮组 --><!-- 小节数据 --><el-collapse-item :title=chapter.title><div v-for="video in chapter.children" :key="video.id">{{ video.title }}<span class="acts"><el-button type="text">编辑</el-button><el-button type="text" @click="removeVideo(video.id)">删除</el-button></span></div></el-collapse-item></el-collapse>

// 删除小节removeVideo(id) {this.$confirm("此操作将永久删除小节信息, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {video.deleteById(id).then((resp) => {this.$message({type: "success",message: "删除成功!",});this.getChapterVideoByCourseId();});});},

2.5、修改小节

<!-- 章节数据折叠面板 --><el-collapse accordion v-for="chapter in chapterVideoList" :key="chapter.id"><!-- 按钮组 --><!-- 小节数据 --><el-collapse-item :title=chapter.title><div v-for="video in chapter.children" :key="video.id">{{ video.title }}<span class="acts"><el-button type="text" @click="openEditVideoForm(video.id)">编辑</el-button><el-button type="text" @click="removeVideo(video.id)">删除</el-button></span></div></el-collapse-item></el-collapse>

// 展开编辑表单openEditVideoForm(id) {this.dialogVideoFormVisible = true;video.getVideoById(id).then((resp) => {this.video = resp.data.data;});},// 修改小节updateVideo() {video.updateVideo(this.video).then((resp) => {this.dialogVideoFormVisible = false;this.$message({message: "修改小节成功",type: "success",});this.getChapterVideoByCourseId();});},// 添加或修改小节saveOrUpdateVideo() {if (this.video.id) {//修改小节this.updateVideo();} else {//新增小节this.saveVideo();}},

三、课程发布信息预览

3.1、后端接口

1、创建 VO

@Datapublic class CoursePublishVo implements Serializable {private static final long serialVersionUID = 1L;private String id;//课程idprivate String title; //课程名称private String cover; //封面private Integer lessonNum;//课时数private String subjectLevelOne;//一级分类private String subjectLevelTwo;//二级分类private String teacherName;//讲师名称private String price;//价格 ,只用于显示}

2、控制层

// 根据课程id查询课程确认信息@GetMapping("/getPublishCourseInfo/{id}")public R getPublishCourseInfo(@PathVariable String id) {CoursePublishVo publishCourseInfo = eduCourseService.getPublishCourseInfo(id);return R.ok().data("data", publishCourseInfo);}

3、业务层

@Overridepublic CoursePublishVo getPublishCourseInfo(String id) {return eduCourseMapper.getPublishCourseInfo(id);}

4、数据层

CoursePublishVo getPublishCourseInfo(String id);

<select id="getPublishCourseInfo" resultType="com.laptoy.eduservice.entity.vo.CoursePublishVo">SELECT ec.id,ec.title,ec.cover,ec.lesson_num AS lessonNum,ec.price,s1.titleAS subjectLevelOne,s2.titleAS subjectLevelTwo,t.name AS teacherNameFROM edu_course ecLEFT JOIN edu_teacher t ON ec.teacher_id = t.idLEFT JOIN edu_subject s1 ON ec.subject_parent_id = s1.idLEFT JOIN edu_subject s2 ON ec.subject_id = s2.idWHERE ec.id = #{id}</select>

5、将xml文件放到 resources/xml 目录下,并再YML文件指定

mybatis-plus:mapper-locations: /mapper/*.xml

3.3、前端实现

1、定义API - course.js

//课程确认信息显示getPublishCourseInfo(courseId){return request({url:"/eduservice/course/getpublishCourseInfo/"+courseId,method: 'get',})}

2、页面

<div class="ccInfo"><img :src="publishCourseInfo.cover" /><div class="main"><h2>{{ publishCourseInfo.title }}</h2><p class="gray"><span>共{{ publishCourseInfo.lessonNum }}课时</span></p><p><span>所属分类:{{ publishCourseInfo.subjectLevelOne }} : {{ publishCourseInfo.subjectLevelTwo }}</span></p><p>课程讲师:{{ publishCourseInfo.teacherName }}</p><h3 class="red">¥{{ publishCourseInfo.price }}</h3></div></div>

3、方法

export default {data() {return {saveBtnDisabled: false,courseId: '',publishCourseInfo: {},};},methods: {//根据课程id查询getPublishCourseInfo() {course.getPublishCourseInfo(this.courseId).then(resp => {this.publishCourseInfo = resp.data.dataconsole.log(this.publishCourseInfo)})},// 跳转到上一步previous() {this.$router.push("/course/chapter/" + this.courseId);},publish() {this.$router.push("/course/list");}},created() {//获取路由中的id值if (this.$route.params && this.$route.params.id) {this.courseId = this.$route.params.id//调用接口方法根据课程id查询课程信息this.getPublishCourseInfo()}},};

4、css

<style scoped>.ccInfo {background: #f5f5f5;padding: 20px;overflow: hidden;border: 1px dashed #ddd;margin-bottom: 40px;position: relative;}.ccInfo img {background: #d6d6d6;width: 500px;height: 278px;display: block;float: left;border: none;}.ccInfo .main {margin-left: 520px;}.ccInfo .main h2 {font-size: 28px;margin-bottom: 30px;line-height: 1;font-weight: normal;}.ccInfo .main p {margin-bottom: 10px;word-wrap: break-word;line-height: 24px;max-height: 48px;overflow: hidden;}.ccInfo .main p {margin-bottom: 10px;word-wrap: break-word;line-height: 24px;max-height: 48px;overflow: hidden;}.ccInfo .main h3 {left: 540px;bottom: 20px;line-height: 1;font-size: 28px;color: #d32f24;font-weight: normal;position: absolute;}</style>

5、测试

四、课程发布

4.1、后端接口

1、控制层

//课程最终发布//修改课程状态@PostMapping("publishCourse/{id}")public R publishCourse(@PathVariable String id){EduCourse eduCourse = new EduCourse();eduCourse.setStatus("Normal"); //设置课程发布状态eduCourse.setId(id);boolean flag = eduCourseService.updateById(eduCourse);if (flag){return R.ok();}else {return R.error();}}

4.2、前端页面

1、API

//课程最终发布publishCourse(courseId) {return request({url: "/eduservice/course/publishCourse/" + courseId,method: 'post',})}

2、方法

//发布课程publish() {this.$confirm("你确定要发布此课程, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {course.publishCourse(this.courseId).then((resp) => {this.$message({message: "课程发布成功",type: "success",});//跳转课程列表页面this.$router.push({path: "/course/list" });});});}

五、课程列表

5.1、后端接口

1、实体类作为模糊查询条件

@ApiModel(value = "Course查询对象", description = "课程查询对象封装")@Datapublic class CourseQuery implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "课程名称,模糊查询")private String title;@ApiModelProperty(value = "发布状态 Normal已发布 Draft未发布")private String status;}

2、控制层

//多条件查询课程带分页@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("data", records);}

3、业务层

@Overridepublic 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);}

5.2、前端实现

1、页面

<template><div><!--多条件查询表单--><el-form :inline="true" class="demo-form-inline" style="margin-left: 20px; margin-top: 12px"><el-form-item label="课程名称"><el-input v-model="courseQuery.title" 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><!-- 展示表格 --><el-table :data="list" style="width: 100%" height="620" 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="400"></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="100" /><el-table-column prop="gmtCreate" label="添加时间" width="300" /><el-table-column prop="viewCount" label="浏览数量" width="200" /><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" plain>编辑基本信息</el-button></router-link><router-link :to="'/teacher/edit/' + scope.row.id"><el-button type="info" size="mini" icon="el-icon-edit" plain>编辑课程大纲</el-button></router-link><el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(scope.row.id)" plain>点击删除课程</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></div></template>

2、API - course.js

//课程列表多条件分页查询//page:当前页,limit:每页记录数,teacherQuery:条件对象getCourseListPage(page, limit, courseQuery) {return request({url: `/eduservice/course/pageCourseCondition/${page}/${limit}`,method: 'post',data: courseQuery})},

3、js

import course from "@/api/teacher/course.js";export default {data() {return {list: null, //查询之后给接口返回的数据装的集合page: 1, //当前页limit: 10, //每页显示记录数courseQuery: {}, //条件封装对象total: 0, //总记录数};},created() {this.getList();},methods: {getList(page = 1) {this.page = page;course.getCourseListPage(this.page, this.limit, this.courseQuery).then((resp) => {this.list = resp.data.data;this.total = resp.data.total;}) //请求成功.catch((err) => {console.log(err);}); //请求失败},//清空方法resetData() {//表单输入项数据清空this.courseQuery = {};//查询所有课程数据this.getList();},},};

六、课程删除

6.1、后端接口

1、控制层

//课程列表中删除课程方法@DeleteMapping("/removeCourseById/{id}")public R removeCourseById(@PathVariable String id) {boolean flag = eduCourseService.removeCourse(id);if (flag) {return R.ok();} else {return R.error();}}

2、业务层

//删除课程@Transactional@Overridepublic boolean removeCourse(String id) {//1、根据课程id删除小节eduVideoService.removeVideoByCourseId(id);//2、根据课程id删除章节部分eduChapterService.removeChapterByCourseId(id);//3、根据课程id删除课程描述descriptionService.removeById(id);//4、根据课程id删除课程本身boolean flag = this.removeById(id);if (flag) {return true;} else {throw new LaptoyException(20001, "删除失败");}}

3、删除小节

//根据课程id删除小节// TODO 删除小节,要删除对应的视频文件@Overridepublic void removeVideoByCourseId(String id) {QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();wrapper.eq("course_id", id);baseMapper.delete(wrapper);}

4、删除章节

@Overridepublic void removeChapterByCourseId(String id) {QueryWrapper<EduChapter> wrapper = new QueryWrapper<>();wrapper.eq("course_id",id);baseMapper.delete(wrapper);}

6.2、前端实现

1、API - course.js

//删除课程removeCourseById(courseId) {return request({url: "/eduservice/course/removeCourseById/" + courseId,method: 'delete',})}

2、方法

<el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(scope.row.id)" plain>点击删除课程</el-button><script>// 删除课程removeById(id) {this.$confirm("此操作将永久删除该课程记录, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {course.removeCourseById(id).then((resp) => {this.$message({type: "success",message: "删除成功!",});this.getList();});});},</script>

七、编辑基本信息及大纲

1、页面

<el-table-column label="操作" align="center"><template slot-scope="scope"><router-link :to="'/course/info/' + scope.row.id"><el-button type="primary" size="mini" icon="el-icon-edit" plain>编辑基本信息</el-button></router-link><router-link :to="'/course/chapter/' + scope.row.id"><el-button type="info" size="mini" icon="el-icon-edit" plain>编辑课程大纲</el-button></router-link><el-button type="danger" size="mini" icon="el-icon-delete" @click="removeById(scope.row.id)" plain>点击删除课程</el-button></template></el-table-column>

2、添加路由

{path: 'info/:id',name: 'EduCourseInfoEdit',component: () => import('@/views/edu/course/info.vue'),meta: {title: '编辑课程基本信息', noCache: true },hidden: true},{path: 'chapter/:id',name: 'EduCourseChapterEdit',component: () => import('@/views/edu/course/chapter.vue'),meta: {title: '编辑课程大纲', noCache: true },hidden: true},

八、阿里云视频点播

8.1、简介

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

开通服务-按流量计费

8.2、使用

1、开启 存储管理

2、添加 转码模板组

3、上传视频

九、使用服务端SDK

9.1、简介

1、简介

sdk的方式将api进行了进一步的封装,不用自己创建工具类。我们可以基于服务端SDK编写代码来调用点播API,实现对点播产品和服务的快速操作

2、功能介绍

SDK封装了对API的调用请求和响应,避免自行计算较为繁琐的 API签名。支持所有点播服务的API,并提供了相应的示例代码。支持7种开发语言,包括:Java、Python、PHP、.NET、Node.js、Go、C/C++。通常在发布新的API后,我们会及时同步更新SDK,所以即便您没有找到对应API的示例代码,也可以参考旧的示例自行实现调用。

9.2、获取视频

1、在 service模块 新建微服务模块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>joda-time</groupId><artifactId>joda-time</artifactId></dependency>

3、测试获取视频播放地

//初始化类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;}public static void main(String[] args) throws ClientException {//1、根据视频id获取视频播放地址//创建初始化对象DefaultAcsClient cl = InitObject.initVodClient("LTAI5tL5FrVJBuQadij4KRvJ", "Xs7dHUvxCdHLd0K5iFK7NWEbdUN7GG");//创建获取视频地址request对象和response对象GetPlayInfoResponse response = new GetPlayInfoResponse();GetPlayInfoRequest request = new GetPlayInfoRequest();//向request对象设置视频id值request.setVideoId("1a383ac7aa7f4b8197714ca6f886e5be");//调用初始化对象里面的方法传递request,获取数据response = cl.getAcsResponse(request);List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();//播放地址for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) {System.out.print("PlayInfo.PlayURL = " + playInfo.getPlayURL() + "\n");}//Base信息System.out.print("VideoBase.Title = " + response.getVideoBase().getTitle() + "\n");//VideoBase.Title = 6 - What If I Want to Move Faster.mp4}}

PlayInfo.PlayURL = https://outin-327a9fa3dcae11ecbc2400163e1c8dba.oss-cn-/sv/60fc3bbf-180ff24e597/60fc3bbf-180ff24e597.mp4?Expires=1653551691&OSSAccessKeyId=LTAIrkwb21KyGjJl&Signature=h0s4mbCbwFd8797gs1KXWxJAUpU%3DVideoBase.Title = 视频点播控制台 - Google Chrome -05-25 21-26-51.mp4

3、测试获取视频播放凭证(加密视频)

public static void main(String[] args) throws ClientException {//创建初始化对象DefaultAcsClient cl = InitObject.initVodClient("LTAI5tL5FrVJBuQadij4KRvJ", "Xs7dHUvxCdHLd0K5iFK7NWEbdUN7GG");//创建获取视频地址request对象和response对象GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();//向request对象设置视频id值request.setVideoId("1a383ac7aa7f4b8197714ca6f886e5be");GetVideoPlayAuthResponse response = cl.getAcsResponse(request);//播放凭证System.out.print("PlayAuth = " + response.getPlayAuth() + "\n");//VideoMeta信息System.out.print("VideoMeta.Title = " + response.getVideoMeta().getTitle() + "\n");}

PlayAuth = eyJTZWN1cml0eVRva2VuIjoiQ0FJU2h3TjFxNkZ0NUIyeWZTaklyNWJESGZqVG40eHA0cUM1ZWw3WTFuay9kZUZHdWJmOW1qejJJSDlJZEhWb0FPOGZ2dlUwbTJ0WTdQc1psck1xR3NFZUhoZWJONUlwdDg0T29GMzlKcExGc3QySjZyOEpqc1VZcDVBQTdFYXBzdlhKYXNEVkVmbDJFNVhFTWlJUi8wMGU2TC8rY2lyWXBUWEhWYlNDbFo5Z2FQa09Rd0M4ZGtBb0xkeEtKd3hrMnQxNFVtWFdPYVNDUHdMU2htUEJMVXhtdldnR2wyUnp1NHV5M3ZPZDVoZlpwMXI4eE80YXhlTDBQb1AyVjgxbExacGxlc3FwM0k0U2M3YmFnaFpVNGdscjhxbHg3c3BCNVN5Vmt0eVdHVWhKL3phTElvaXQ3TnBqZmlCMGVvUUFQb3BGcC9YNmp2QWF3UExVbTliWXhncGhCOFIrWGo3RFpZYXV4N0d6ZW9XVE84MCthS3p3TmxuVXo5bUxMZU9WaVE0L1ptOEJQdzQ0RUxoSWFGMElVRTF5R21DQ2QvWDRvZ3VSUDF6N0VwTG9pdjltamNCSHFIeno1c2VQS2xTMVJMR1U3RDBWSUpkVWJUbHphRUpHZ1RTNExmWldJbGNUS0FNOVd1MlBNYXgzYlFGRHI1M3ZzVGJiWHpaYjBtcHR1UG56ZDE0Sk9CS2cxMUtVR29BQlUrY0Q3SXpmeDIvSHJmNXA2cWdSa2UvdDNaMjFPUXF1NkRsSkV3VnpPL2poWngva3JNNitGNWlEK25kT1JHQitZbDJtcTN6SlBnclQxNVdveE5QdXJndy9xbWNib1BWR3dtV01qa3RKOXo0YS90TnA0SWNLRGxKQStvOWFvOWdLbUpPZWJFMnZXT1FicE1LbGFmOER6Q1JCMTl5NmZDUi9qWDFObndub3RTQT0iLCJBdXRoSW5mbyI6IntcIkNJXCI6XCJLenVKNUlCVmRIc0E2eTNlTXFDbS9vYXVOMFZwVFBmYkU0L1VaUUt5c0dhVzc3MjRTWEZQejVyUHlyOGRSN0VaZXVFenpEdndDcDRIY2NoZFlkMjdMVy8yK0R2S1lySXRsVGxlTCtUa0lsZz1cIixcIkNhbGxlclwiOlwiNldQZVY4MkttMDlUbGNGUzVWeDB0SjUxY2pCWEVYb2FuZEk4dEU4OENjWT1cIixcIkV4cGlyZVRpbWVcIjpcIjIwMjItMDUtMjZUMDc6MDQ6NTZaXCIsXCJNZWRpYUlkXCI6XCIxYTM4M2FjN2FhN2Y0YjgxOTc3MTRjYTZmODg2ZTViZVwiLFwiU2lnbmF0dXJlXCI6XCI3Vjhza3RPTnRIK1NBZGV0bVFWRk9CU29vRmc9XCJ9IiwiVmlkZW9NZXRhIjp7IlN0YXR1cyI6Ik5vcm1hbCIsIlZpZGVvSWQiOiIxYTM4M2FjN2FhN2Y0YjgxOTc3MTRjYTZmODg2ZTViZSIsIlRpdGxlIjoi6KeG6aKR54K55pKt5o6n5Yi25Y+wIC0gR29vZ2xlIENocm9tZSAyMDIyLTA1LTI1IDIxLTI2LTUxLm1wNCIsIkNvdmVyVVJMIjoiaHR0cDovL291dGluLTMyN2E5ZmEzZGNhZTExZWNiYzI0MDAxNjNlMWM4ZGJhLm9zcy1jbi1zaGFuZ2hhaS5hbGl5dW5jcy5jb20vMWEzODNhYzdhYTdmNGI4MTk3NzE0Y2E2Zjg4NmU1YmUvc25hcHNob3RzLzNmOTg0ZTE0YjU5OTQxNTM5ODhmNDdiMGI1MDQxMDZhLTAwMDAxLmpwZz9FeHBpcmVzPTE2NTM1NTIxOTYmT1NTQWNjZXNzS2V5SWQ9TFRBSXJrd2IyMUt5R2pKbCZTaWduYXR1cmU9c040UEljem9UbUFPSFJzaHhRTXhMd3pxc09vJTNEIiwiRHVyYXRpb24iOjUuMzE3N30sIkFjY2Vzc0tleUlkIjoiU1RTLk5VdlZCZ3JTSFViUnh4aTJ5anlualZyVngiLCJBY2Nlc3NLZXlTZWNyZXQiOiI3dzRnaWtuSEFlbndCTVYxN2hqbXNqekw4cUZIdlRmZ0tHNjFtWDJ1cVdKcCIsIlJlZ2lvbiI6ImNuLXNoYW5naGFpIiwiQ3VzdG9tZXJJZCI6MTk2MzMzNzIxMTEyMTk2NH0=VideoMeta.Title = 视频点播控制台 - Google Chrome -05-25 21-26-51.mp4

9.3、上传视频

1、POM - 默认找不到该依赖

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

2、将资料的5-lib/aliyun-java-vod-upload-1.4.11.jar放到maven仓库bin目录下并执行如下命令安装上述依赖

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

3、测试

@Testpublic void testFileUpload() {String accessKeyId = "LTAI5tL5FrVJBuQadij4KRvJ";String accessKeySecret = "Xs7dHUvxCdHLd0K5iFK7NWEbdUN7GG";String title = "My Upload Video"; //上传之后文件的名称String fileName = "C:\\Users\\lapto\\Desktop\\myVideo.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");}}

十、视频点播微服务

10.1、后端接口

1、service_vod微服务 主启动类

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

2、YML

# 服务端口号server.port=8003# 服务名spring.application.name=service-vod# nacos注册中心spring.cloud.nacos.discovery.server-addr=120.76.55.55:8848# 环境设置 dev test prodspring.profiles.active=dev# 最大上传单个文件大小:默认1Mspring.servlet.multipart.max-file-size=1024MB# 最大置总上传的数据大小 :默认10Mspring.servlet.multipart.max-request-size=1024MB# 阿里云 vodaliyun.vod.file.keyid=LTAI5tL5FrVJBuQadij4KRvJaliyun.vod.file.keysecret=Xs7dHUvxCdHLd0K5iFK7NWEbdUN7GG

3、控制层

@RestController@CrossOrigin@RequestMapping("/eduvod/video")public class VodController {@Autowiredprivate VodService vodService;//上传视频到阿里云@PostMapping("/uploadAliyunVideo")public R uploadAliyunVideo(MultipartFile file) {//返回上传视频的idString videoId = vodService.uploadVideoAliyun(file);return R.ok().data("data", videoId);}}

4、业务层

@Servicepublic class VodServiceImpl implements VodService {@Value("${aliyun.vod.file.keyid}")private String accessKeyId;@Value("${aliyun.vod.file.keysecret}")private String accessKeySecret;@Overridepublic String uploadVideoAliyun(MultipartFile file) {try {//fileName:上传文件原始名称String fileName = file.getOriginalFilename();//title:上传之后显示名称String title = fileName.substring(0, fileName.lastIndexOf("."));//inputStream:上传文件的输入流InputStream inputStream = file.getInputStream();UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, inputStream);UploadVideoImpl uploader = new UploadVideoImpl();UploadStreamResponse response = uploader.uploadStream(request);System.out.print("RequestId=" + response.getRequestId() + "\n"); //请求视频点播服务的请求IDString videoId = null;if (response.isSuccess()) {videoId = response.getVideoId();} else {//如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因videoId = response.getVideoId();}return videoId;} catch (Exception e) {e.printStackTrace();return null;}}}

5、测试

10.2、前端实现

1、nginx.conf 添加配置并重启 nginx

http {<--文件上传最大大小 --> client_max_body_size 1024m;server {listen 9001;server_name localhost;...location ~ /eduvod/ {proxy_pass http://localhost:8003;}}}

2、页面

<el-form-item label="上传视频"><el-upload class="upload-demo" :on-success="handleVodUploadSuccess" :before-remove="beforeVodRemove" :file-list="fileList" :action="BASE_API + '/eduvod/video/uploadAliyunVideo'" :limit="1" ><el-button size="small" type="primary">上传视频</el-button><el-tooltip placement="right-end"><!-- 隐藏提示信息 --><div slot="content">最大支持1G,<br />支持3GP、ASF、AVI、DAT、DV、FLV、F4V、<br />GIF、M2T、M4V、MJ2、MJPEG、MKV、MOV、MP4、<br />MPE、MPG、MPEG、MTS、OGG、QT、RM、RMVB、<br />SWF、TS、VOB、WMV、WEBM 等视频格式上传</div><i class="el-icon-question" /></el-tooltip></el-upload></el-form-item>

3、js

data() {return {video: {sort: 0,title: "",free: "",videoSourceId: ""},fileList: [], //上传文件列表BASE_API: process.env.BASE_API, // 接口API地址};},methods: {// 上传成功执行方法handleVodUploadSuccess(response, file, fileList) {this.video.videoSourceId = response.data.data},beforeVodRemove(file, fileList) {return this.$confirm(`确定移除 ${file.name}?`);},}

10.3、视频删除

1、控制层

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

2、业务层

// 根据id删除阿里云视频@Overridepublic void removeAliyunVideoById(String id) {try {DefaultAcsClient client = initVodClient(accessKeyId, accessKeySecret);DeleteVideoRequest request = new DeleteVideoRequest();request.setVideoIds(id);DeleteVideoResponse response = client.getAcsResponse(request);System.out.println("RequestId = " + response.getRequestId() + "\n");} catch (ClientException e) {throw new LaptoyException(20001, "视频删除失败");}}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;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。