一、课程最终发布信息展示 – 后端

1、实体类—用于封装页面显示的数据

@ApiModel(value = "课程最终发布")
@Data
public class CoursePublishVo implements Serializable {private static final long serialVersionUID = 1L;//课程标题private String title;//课程封面private String cover;//课时数private Integer lessonNum;//一级分类private String subjectLevelOne;//二级分类private String subjectLevelTwo;//讲师名称private String teacherName;//课程价格private String price;//只用于显示
}

2、编写Controller类

//课程发布
//根据课程id查询课程的发布信息
@ApiOperation("查询课程发布信息")
@GetMapping("getPublishCourseInfo/{id}")
public R getPublishCourseInfo(@PathVariable String id){CoursePublishVo courseInfo =  courseService.getPublishCourseInfo(id);return R.ok().data("courseInfo",courseInfo);
}

3、编写Service类

//根据id查询课程发布信息
@Override
public CoursePublishVo getPublishCourseInfo(String id) {CoursePublishVo coursePublishVo = this.baseMapper.getPublishCourseInfo(id);return coursePublishVo;
}

由于我们最终发布页面显示的数据是来源于四张表(课程表、课程描述表、讲师表、分类表),所以我们需要手动写SQL语句实现。

4、编写mapper接口

public interface EduCourseMapper extends BaseMapper<EduCourse> {public CoursePublishVo getPublishCourseInfo(String id);
}

5、编写mapper类xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rg.eduservice.mapper.EduCourseMapper"><select id="getPublishCourseInfo" resultType="com.rg.eduservice.entity.vo.CoursePublishVo" parameterType="string">SELECT ec.id,ec.`title`,ec.`price`,ec.`lesson_num` AS lessonNum,ec.`cover`,et.`name` teacherName,es1.`title` AS subjectLevelOne,es2.`title` AS subjectLevelTwoFROM edu_course ec LEFT OUTER JOIN edu_subject es1 ON ec.`subject_parent_id`= es1.`id`LEFT OUTER JOIN edu_subject es2 ON ec.`subject_id` = es2.`id`LEFT OUTER JOIN edu_teacher et ON ec.`teacher_id` = et.`id`WHERE ec.id=#{id}</select>
</mapper>

6、项目运行出现错误并解决

项目创建mapper接口,编写xml文件sql语句,执行出现错误

这个错误是由maven默认加载机制造成问题。maven加载时候,把java文件夹里面 .java 类型文件进行编译,如果其他类型文件,不会加载。

解决方式:
1、复制xml到target目录中
2、把xml文件放在resources目录中
3、推荐使用:通过配置文件实现
(1)pom.xml
(2)项目application.properties

<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources>
</build>

在service模块的application.properties中

# 配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/kuang/eduservice/mapper/xml/*.xml

重新启动服务即可运行成功!

二、课程最终发布信息展示 – 前端

1、定义api接口

//根据课程id查询课程发布的基本信息
getPublishCourseInfo(id) {return request({url: `/eduservice/course/getPublishCourseInfo/${id}`,method: 'get'})
}

2、前端页面和样式

<template><div class="app-container"><h2 style="text-align: center;">发布新课程</h2><el-steps :active="3" process-status="wait" align-center style="margin-bottom: 40px;"><el-step title="填写课程基本信息"/><el-step title="创建课程大纲"/><el-step title="发布课程"/></el-steps><div class="ccInfo"><img :src="coursePublish.cover"><div class="main"><h2>{{ coursePublish.title }}</h2><p class="gray"><span>共{{ coursePublish.lessonNum }}课时</span></p><p><span>所属分类:{{ coursePublish.subjectLevelOne }} — {{ coursePublish.subjectLevelTwo }}</span></p><p>课程讲师:{{ coursePublish.teacherName }}</p><h3 class="red">¥{{ coursePublish.price }}</h3></div></div><div><el-button @click="previous">返回修改</el-button><el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button></div></div>
</template>
<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>

3、引入接口

import course from '@/api/edu/course'

4、编写前端js

data() {return {//....saveBtnDisabled:false,courseId: '',coursePublish: {}}},created() {//获取路由中id值if(this.$route.params && this.$route.params.id) {this.courseId = this.$route.params.id//调用接口方法根据课程id查询this.getPublishCourseInfo()}},methods: {//根据课程id查询课程信息  getPublishCourseInfo(){course.getPublishCourseInfo(this.courseId).then(response=>{this.coursePublish = response.data.courseInfo})}//.....}

5、页面效果图

三、课程最终发布 – 前后端

1、编写Controller类

//课程发布
@PutMapping("publishCourse/{id}")
public R publishCourse(@PathVariable String id){EduCourse course = new EduCourse();course.setId(id);course.setStatus("Normal");boolean update = courseService.updateById(course);if(update){return R.ok();}else{return R.error();}
}

2、定义api接口

//发布课程信息
publishCourse(id) {return request({url: `/eduservice/course/publishCourse/${id}`,method: 'put'})
}

3、编写前端js

publish(){course.publishCourse(this.courseId).then(response=>{this.$confirm('确认发布此课程吗,是否继续?','提示',{confirmButtonText:'确定',cancelButtonText:'取消',type:'warning'}).then(()=>{//点击确定this.$message({type:'success',message:'课程发布成功!' }) //跳转到课程列表页面this.$router.push({path:'/course/list'})}).catch(()=>{this.$message({type: 'info',message: '已取消发布!'})})}).catch(()=>{this.$message({type: 'error',message: '课程发布失败!'})})
}

四、课程列表 – 后端

1、编写查询实体类

@Data
public class CourseQuery implements Serializable {private static final long serialVersionUID = 1L;//一级分类idprivate String subjectParentId;//二级分类idprivate String subjectId;//课程名称private String title;//讲师idprivate String teacherId;}

2、Controller类

//分页查询课程
@PostMapping("pageQuery/{current}/{limit}")
public R pageQuery(@PathVariable Integer current,@PathVariable Integer limit,@RequestBody CourseQuery courseQuery)
{Page<EduCourse> page =  courseService.pageQuery(current,limit,courseQuery);return R.ok().data("total",page.getTotal()).data("list",page.getRecords());
}//删除课程
@DeleteMapping("removeCourse/{id}")
public R removeCourse(@PathVariable String id){courseService.removeCourse(id);return R.ok();
}

3、Service类

//对课程进行分页查询
@Override
public Page <EduCourse> pageQuery(Integer current, Integer limit, CourseQuery courseQuery) {Page <EduCourse> page = new Page <>(current,limit);QueryWrapper <EduCourse> wrapper = new QueryWrapper <>();String title = courseQuery.getTitle();String subjectId = courseQuery.getSubjectId();String subjectParentId = courseQuery.getSubjectParentId();String teacherId = courseQuery.getTeacherId();//判空,构造查询条件if(!StringUtils.isEmpty(title)){wrapper.like("title",title);}if(!StringUtils.isEmpty(subjectId)){wrapper.eq("subject_id",subjectId);}if(!StringUtils.isEmpty(subjectParentId)){wrapper.eq("subject_parent_id",subjectParentId);}if(!StringUtils.isEmpty(teacherId)){wrapper.eq("teacher_id",teacherId);}wrapper.orderByDesc("gmt_create");//进行分页查询this.baseMapper.selectPage(page, wrapper);//分页查询后自动封装到page中return page;
}//根据id删除课程信息
@Override
public void removeCourse(String id) {//1.删除小节videoService.removeVideoByCourseId(id);//2.删除章节chapterService.removeChapterByCourseId(id);//3.删除课程描述信息courseDescriptionService.removeById(id);//4.删除课程信息this.baseMapper.deleteById(id);
}

五、课程列表 – 前端

1、定义api接口

//删除课程
removeCourse(id) {return request({url: `/eduservice/course/removeCourse/${id}`,method: 'delete'})
},
//分页查询课程
pageQuery(current, limit, courseQuery) {return request({url: `/eduservice/course/pageQuery/${current}/${limit}`,method: 'post',data: courseQuery})
}

2、 前端页面—list.vue

<template><div class="app-container"><!--查询表单--><el-form :inline="true" class="demo-form-inline"><!-- 所属分类:级联下拉列表 --><!-- 一级分类 --><el-form-item label="课程类别"><el-selectv-model="searchObj.subjectParentId"placeholder="请选择"@change="subjectLevelOneChanged"><el-optionv-for="subject in subjectNestedList":key="subject.id":label="subject.title":value="subject.id"/></el-select><!-- 二级分类 --><el-select v-model="searchObj.subjectId" placeholder="请选择"><el-optionv-for="subject in subSubjectList":key="subject.id":label="subject.title":value="subject.id"/></el-select></el-form-item><!-- 标题 --><el-form-item><el-input v-model="searchObj.title" placeholder="课程标题"/></el-form-item><!-- 讲师 --><el-form-item><el-selectv-model="searchObj.teacherId"placeholder="请选择讲师"><el-optionv-for="teacher in teacherList":key="teacher.id":label="teacher.name":value="teacher.id"/></el-select></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><!-- 表格 --><el-tablev-loading="listLoading":data="list"element-loading-text="数据加载中"borderfithighlight-current-rowrow-class-name="myClassList"><el-table-columnlabel="序号"width="70"align="center"><template slot-scope="scope">{{ (page - 1) * limit + scope.$index + 1 }}</template></el-table-column><el-table-column label="课程信息" width="470" align="center"><template slot-scope="scope"><div class="info"><div class="pic"><img :src="scope.row.cover" alt="scope.row.title" width="150px"></div><div class="title"><a href="">{{ scope.row.title }}</a><p>{{ scope.row.lessonNum }}课时</p></div></div></template></el-table-column><el-table-column label="创建时间" align="center"><template slot-scope="scope">{{ scope.row.gmtCreate.substr(0, 10) }}</template></el-table-column><el-table-column label="发布时间" align="center"><template slot-scope="scope">{{ scope.row.gmtModified.substr(0, 10) }}</template></el-table-column><el-table-column label="价格" width="100" align="center" ><template slot-scope="scope">{{ Number(scope.row.price) === 0 ? '免费' :'¥' + scope.row.price.toFixed(2) }}</template></el-table-column><el-table-column prop="buyCount" label="付费学员" width="100" align="center" ><template slot-scope="scope">{{ scope.row.buyCount }}人</template></el-table-column><el-table-column prop="viewCount" label="播放次数" width="100" align="center" ><template slot-scope="scope">{{ scope.row.viewCount }}次</template></el-table-column><el-table-column label="操作" width="150" align="center"><template slot-scope="scope"><router-link :to="'/course/info/'+scope.row.id"><el-button type="text" size="mini" icon="el-icon-edit" >编辑课程信息</el-button></router-link><router-link :to="'/course/chapter/'+scope.row.id"><el-button type="text" size="mini" icon="el-icon-edit" >编辑课程大纲</el-button></router-link><el-button type="text" size="mini" icon="el-icon-delete" @click="removeCourse(scope.row.id)">删除</el-button></template></el-table-column></el-table><!-- 分页 -->
<el-pagination:current-page="page":page-size="limit":total="total"style="padding: 30px 0; text-align: center;"layout="total, prev, pager, next, jumper"@current-change="getList"
/></div>
</template>

3、页面样式

<style scoped>
.myClassList .info {width: 450px;overflow: hidden;
}
.myClassList .info .pic {width: 150px;height: 90px;overflow: hidden;float: left;
}
.myClassList .info .pic a {display: block;width: 100%;height: 100%;margin: 0;padding: 0;
}
.myClassList .info .pic img {display: block;width: 100%;
}
.myClassList td .info .title {width: 280px;float: right;height: 90px;
}
.myClassList td .info .title a {display: block;height: 48px;line-height: 24px;overflow: hidden;color: #00baf2;margin-bottom: 12px;
}
.myClassList td .info .title p {line-height: 20px;margin-top: 5px;color: #818181;
}
</style>

4、编写前端js

<script>
import course from '@/api/edu/course'
import subject from '@/api/edu/subject'
export default {data() {return {listLoading: false, // 是否显示loading信息list: null, // 数据列表total: 0, // 总记录数page: 1, // 页码limit: 10, // 每页记录数searchObj: {subjectParentId: '',subjectId: '',title: '',teacherId: ''}, // 查询条件teacherList: [], // 讲师列表subjectNestedList: [], // 一级分类列表subSubjectList: [] // 二级分类列表,}},created() {this.init()},methods: {//编辑课程大纲updateChapter(id){this.$router.push({path:'/course/chapter/'+id})},//编辑课程基本信息updateCourse(id){this.$router.push({path:'/course/info/'+id})},removeCourse(id){this.$confirm('此操作将永久删除该课程的所有内容,是否继续?','提示',{confirmButtonText:'确定',cancelButtonText:'取消',type:'warning'}).then(()=>{//点击确定course.removeCourse(id).then((response)=>{this.$message({type:'success',message:'删除成功!' }) //回到列表页面this.getList()}).catch(()=>{this.$message({type:'error',message:'删除失败!' }) })}).catch(() => { // 点击取消this.$message({type: 'info',message: '已取消删除!'})})},//分页+条件查询getList(page = 1){//page默认值为1,当使用分页组件时会传入新的page参数this.page = pagecourse.pageQuery(this.page,this.limit,this.searchObj).then(response=>{this.list = response.data.listthis.total = response.data.total})},//查询表单重置方法resetData(){this.searchObj = {},this.subSubjectList = []},//当一级分类下拉菜单改变时的方法subjectLevelOneChanged(id){// console.log(id);for(var i = 0;i < this.subjectNestedList.length;i++){if(this.subjectNestedList[i].id == id){this.subSubjectList = this.subjectNestedList[i].children}}},//初始化方法init(){//1.查询一级分类subject.getAllSubject().then(response=>{this.subjectNestedList = response.data.list})//2.查询所有讲师course.getTeacherList().then(response=>{this.teacherList = response.data.items})//3.查询课程列表this.getList()}}
}
</script>

五、页面效果图

六、阿里云视频点播服务

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

1、开通视频点播

进入阿里云官网:https://www.aliyun.com/,找到视频点播

开通视频点播服务(选择按流量计费)

2、资费说明

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

3、整体流程

使用视频点播实现音视频上传、存储、处理和播放的整体流程如下:

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

完整的参考文档 https://help.aliyun.com/product/29932.html?spm=a2c4g.11186623.6.540.3c356a58OEmVZJ

  • 服务端:后端接口

  • 客户端:浏览器、安卓、ios

  • API:阿里云提供固定的地址,只需要调用这个固定的地址,向地址传递参数,实现功能。

  • SDK:sdk对api方式进行封装,更方便使用。之前使用EayExcel调用阿里云提供类或者接口里面的方法实现视频功能。

5、使用Java代码具体使用SDK方式

注意:因为上传视频可以进行加密,加密之后,使用加密之后的地址不能进行视频播放,所以在数据库存储不存地址,而是存储视频id

(1)在service下创建子模块service_vod模块

POM.xml

<dependencies><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.aliyun</groupId><artifactId>aliyun-sdk-vod-upload</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>org.json</groupId><artifactId>json</artifactId></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency>
</dependencies>

(2)初始化操作,创建 DefaultAcsClient 对象

public class InitVodClient {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)实现根据视频id获取视频播放地址

//根据id获取视频播放地址
public static void getPlayUrl()throws ClientException{//创建初始化对象DefaultAcsClient client = InitVodClient.initVodClient("your keyId", "your keySecret");//创建获取视频地址request和responseGetPlayInfoRequest request = new GetPlayInfoRequest();GetPlayInfoResponse response = new GetPlayInfoResponse();request.setVideoId("efc88346e5dd45fda5b161c9ddbd0d9d");//调用初始化对象里面的方法,传递request,获取数据response = client.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");
}

(4)获取视频播放凭证

//根据id获取视频播放凭证
public static void getPlayAuth()throws ClientException{//创建初始化对象DefaultAcsClient client = InitVodClient.initVodClient("your keyId", "your keySecret");GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();GetVideoPlayAuthResponse response = new GetVideoPlayAuthResponse();request.setVideoId("003a83891a7b444d93727d83a5ba7d3a");response = client.getAcsResponse(request);System.out.println("palyAuth:"+response.getPlayAuth());
}

(5)上传视频到阿里云视频点播服务

//以文件流的方式进行上传
public static void testUploadFileStream(){String accessKeyId = "your keyId";String accessKeySecret = "your keySecret";String title = "6 - What If I Want to Move Faster123.mp4 ";String fileName = "F:/自学课程/项目资料/02谷粒学苑(分布式项目)/项目资料/1-阿里云上传测试视频/6 - What If I Want to Move Faster.mp4";UploadFileStreamRequest request = new UploadFileStreamRequest(accessKeyId, accessKeySecret, title, fileName);UploadVideoImpl uploader = new UploadVideoImpl();UploadFileStreamResponse response = uploader.uploadFileStream(request);System.out.print("RequestId=" + response.getRequestId() + "\n"); //请求视频点播服务的请求IDif (response.isSuccess()) {System.out.print("VideoId=" + response.getVideoId() + "\n");} 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");}
}

七、添加小节实现视频上传和删除 – 后端

1、引入依赖

2、创建application配置文件

#服务端口
server:port: 8003#服务名
spring:application:name: service-vod#环境设置:dev,test,prodprofiles:active: devservlet:multipart:max-file-size: 1024MB # 最大上传单个文件大小:默认1Mmax-request-size: 1024MB # 最大置总上传的数据大小 :默认10M#阿里云VOD地址
aliyun:vod:file:keyid: your keyIdkeysecret: your keySecret

3、常量工具类

@Component //把属性的设置交给Spring.
public class ConstantPropertiesUtil implements InitializingBean {// InitializingBean:在初始化的时候,该类被执行.//从配置文件中读取值,赋值给这些属性//注意@value无法给静态属性注入值@Value("${aliyun.vod.file.keyid}")private String keyId;@Value("${aliyun.vod.file.keysecret}")private String keySecret;//定义公开静态方法public static String ACCESS_KEY_ID;public static String ACCESS_KEY_SECRET;//当属性值设置完毕后执行该方法.@Overridepublic void afterPropertiesSet() throws Exception {ACCESS_KEY_ID = keyId;ACCESS_KEY_SECRET = keySecret;}
}

4、主启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan("com.rg")//为了扫描外部的swagger
public class VodApplication {public static void main(String[] args) {SpringApplication.run(VodApplication.class, args);}
}

5、编写Controller类

@RestController
@RequestMapping("/vodService/video")
@CrossOrigin
public class VodController {@Autowiredprivate VodService vodService;//上传视频到阿里云VOD@PostMapping("uploadVideoAly")public R uploadVideoAly(@RequestBody MultipartFile file){String videoId = vodService.uploadVideoAly(file);return R.ok().data("videoId",videoId);}//根据视频id从阿里云删除视频@DeleteMapping("removeAlyVideo/{id}")public R removeAlyVideo(@PathVariable String id){vodService.removeAlyVideo(id);return R.ok();}
}

6、编写Service类

@Service
public class VodServiceImpl implements VodService {//上传视频到阿里云VOD@Overridepublic String uploadVideoAly(MultipartFile file) {String accessKeyId = ConstantPropertiesUtil.ACCESS_KEY_ID;String accessKeySecret = ConstantPropertiesUtil.ACCESS_KEY_SECRET;String title = file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."));//上传之后显示名称String fileName = file.getOriginalFilename();//上传文件原始名称try {InputStream inputStream = file.getInputStream();//上传文件流UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, inputStream);UploadVideoImpl uploader = new UploadVideoImpl();UploadStreamResponse response = uploader.uploadStream(request);String videoId = response.getVideoId();return videoId;} catch (Exception e) {e.printStackTrace();throw new GuLiException(20001, "文件上传失败!");}}//根据id删除阿里云上的视频@Overridepublic void removeAlyVideo(String id) {try {DefaultAcsClient client = InitVodClient.initVodClient(ConstantPropertiesUtil.ACCESS_KEY_ID, ConstantPropertiesUtil.ACCESS_KEY_SECRET);//DeleteVideoRequest request = new DeleteVideoRequest();DeleteVideoResponse response = new DeleteVideoResponse();//想request中设置视频idrequest.setVideoIds(id);response = client.getAcsResponse(request);} catch (ClientException e) {e.printStackTrace();throw new GuLiException(20001, "视频删除失败!");}}
}

八、添加小节实现视频上传和删除 – 前端

1、定义api

//根据id删除视频
removeAlyVideo(id) {return request({url: `/vodService/video/removeAlyVideo/${id}`,method: 'delete'})
}

2、整合上传组件

<el-form-item label="上传视频"><el-upload:on-success="handleVodUploadSuccess":on-remove="handleVodRemove":before-remove="beforeVodRemove":on-exceed="handleUploadExceed":file-list="fileList":action="BASE_API+'/vodService/video/uploadVideoAly'":limit="1"class="upload-demo"><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、数据定义

fileList: [],//上传文件列表
BASE_API: process.env.BASE_API // 接口API地址
video: {// 课时对象title: '',sort: 0,isFree: 0,videoSourceId: '',videoOriginalName:''
}

4、页面js方法

//上传视频超过最大数量的方法
handleUploadExceed(file,fileList){this.$message.warning('想要重新上传视频,请先删除已经上传的视频')
},
//点击确定调用的方法
handleVodRemove(){video.removeAlyVideo(this.video.videoSourceId).then(response=>{this.$message({type:'success',message:'删除视频成功!' }) //把文件列表清空this.fileList = []//删除的视频信息不再存入数据库this.video.videoSourceId = ''this.video.videoOriginalName = ''})},
//点击×调用的方法
beforeVodRemove(file,fileList){return this.$confirm(`确定移除 ${file.name}?`)
},
//上传成功方法
handleVodUploadSuccess(response,file,fileList){this.video.videoSourceId = response.data.videoIdthis.video.videoOriginalName = file.name
}

5、编辑小节时视频回显

6、页面效果展示


如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

谷粒学院(十一)课程最终发布 | 课程列表 | 阿里云视频点播服务 | 小节实现视频上传相关推荐

  1. 谷粒学院day09——课程发布与阿里云视频点播服务

    day9 课程信息确认与视频点播 1.课程信息确认 1.1 后端实现 1.2 前端实现 2.课程的最终发布 3.课程列表功能 4.课程删除功能 5.阿里云视频点播 5.1 获取视频地址 5.2 获取视 ...

  2. html读取oss_阿里云使用js 实现OSS图片上传、获取OSS图片列表(示例代码)

    详情请参考:https://help.aliyun.com/document_detail/32069.html?spm=a2c4g.11186623.6.763.ZgC59a 或者https://h ...

  3. 阿里云使用js 实现OSS图片上传、获取OSS图片列表、获取图片外网访问地址(读写权限私有、读写权限公共);...

    详情请参考:https://help.aliyun.com/document_detail/32069.html?spm=a2c4g.11186623.6.763.ZgC59a 或者https://h ...

  4. 05-阿里云视频点播服务与谷粒学院整合视频点播技术

    阿里云视频点播服务与谷粒学院整合视频点播技术 一.应用场景 音视频网站:无论是初创视频服务企业,还是已拥有海量视频资源,可定制化的点播服务帮助客户快速搭建拥有极致观看体验.安全可靠的视频点播应用. 短 ...

  5. 通过阿里云容器服务K8S Ingress Controller实现应用服务的灰度发布

    简介 日常工作中我们经常需要对服务进行版本更新升级,为此我们经常使用到的发布方式有滚动升级.分批暂停发布.蓝绿发布以及灰度发布,今天主要跟大家分享下在阿里云容器服务Kubernetes集群中如何通过I ...

  6. 阿里云容器服务多项重磅发布:高效智能、安全无界的新一代平台

    在云原生带来的云计算未来趋势下,容器已经成为用户使用云的新界面. 阿里云容器产品发布近 7 年以来,已成长发展为企业的云原生操作系统,技术和服务能力日趋成熟,但创新从未止步.日前,阿里云研究员 &am ...

  7. 谷粒学院(九)EasyExcel | 课程分类模块

    文章目录 一.EasyExcel 简介 1.Excel导入导出的应用场景 2.EasyExcel特点 3.案例1:EasyExcel进行Excel写操作 4.案例2:EasyExcel进行Excel读 ...

  8. 谷粒学院 —— 10、课程管理:整合阿里云视频点播

    目录 1.创建模块 1.1.引入视频点播所需依赖 1.2.application.properties 1.3.启动类 2.实现视频上传 2.1.后端 2.1.1.创建常量类 2.1.2.上传视频到阿 ...

  9. 阿里云容器服务发布 Knative 托管服务 | 云原生生态周报 Vol. 49

    作者 | 何淋波.丁海洋.陈有坤 业界要闻 阿里云容器服务发布 Knative 托管服务 Knative 是 Kubernetes 生态最流行的 Serverless 编排框架.可 Knative 的 ...

  10. 阿里云容器服务发布 Knative 托管服务

    作者 | 何淋波.丁海洋.陈有坤 业界要闻 阿里云容器服务发布 Knative 托管服务 Knative 是 Kubernetes 生态最流行的 Serverless 编排框架.可 Knative 的 ...

最新文章

  1. 为什么说,长跑和爬山能锻炼意志?因为要不停的run,run,run......
  2. python中and与or的执行顺序-python 代码运行顺序问题?
  3. java布局管理怎么有图片_java-用于背景图像和文本的布局管理器
  4. 以一种访问权限不允许的方式做了一个访问套接字的尝试。
  5. Formik官方应用案例解析(三)使用react-select
  6. Unity 之 获取物体的旋转角正确数值
  7. (蓝图)虚幻4重制俄罗斯方块(四)移动方块
  8. FPGA之道(16)FPGA开发流程之项目方案与FPGA设计方案
  9. 机器学习数学篇—基础数学知识清单
  10. 阅读不懂,图书之过——《大话设计模式》创作历程
  11. 二元对数正态分布 (bivariate lognormal distribution) 的几个性质
  12. github whs_从iPhone或iPod Touch获得WHS的基本访问权限,而无需安装应用程序
  13. ChemDraw如何画立体图?
  14. 最大公约数的几种基本求解方法
  15. HPLC鬼峰、基线漂移、拖尾、分叉峰、保留时间漂移、柱压过高等系列问题解析
  16. 某“工匠杯”内部预选赛
  17. ASCII码对照表(128字符)
  18. I-CUBE-LRWAN代码阅读笔记:软件组织架构
  19. C语言连接mysql数据库详细步骤
  20. 保研经验帖(二)夏令营经验分享

热门文章

  1. 哈哈日语 日语学习基础入门----五十音(二)
  2. java 单列集合List 万字详解(通俗易懂)
  3. 形势与政策论文怎么写
  4. html 邮件 附件,HTML电子邮件缺少附件
  5. Restormer Efficient Transformer for High-Resolution Image Restoration论文代码运行记录
  6. 有了它,再也不怕 C++ 内存泄露了!
  7. 4515DO-DS3BK004DP压差传感器MEAS
  8. stm32mp157开发板网卡接口测试
  9. 微信公号开发获得用户信息失败
  10. 一次读懂flex布局