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

2023-05-16

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

1、实体类

@ApiModel(value = "课程最终发布")
@Data
public class CoursePublishVo {
    private String id;
    private String title;
    private String cover;
    private String lessonNum;
    private String subjectLevelOne;
    private String subjectLevelTwo;
    private String teacherName;
    private String price;
}

2、编写Controller类

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

3、编写Service类

@Override
public CoursePublishVo publishCourseInfo(String id) {
    CoursePublishVo publicCourseInfo = baseMapper.getPublicCourseInfo(id);
    return publicCourseInfo;
}

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

public CoursePublishVo getPublicCourseInfo(String courseId);

5、编写mapper类xml配置文件

<!--根据课程id查询课程确定信息-->
<select id="getPublicCourseInfo" resultType="com.kuang.eduservice.entity.vo.CoursePublishVo">
    SELECT ec.id,ec.title,ec.price,ec.lesson_num AS lessonNum,ec.cover,
                et.name AS teacherName,
                es1.title AS subjectLevelOne,
                es2.title AS subjectLevelTwo
    FROM edu_course ec LEFT JOIN edu_course_description ecd ON ec.id=ecd.id
                                         LEFT JOIN edu_teacher et ON ec.teacher_id=et.id
                                         LEFT JOIN edu_subject es1 ON ec.subject_parent_id=es1.id
                                         LEFT JOIN edu_subject es2 ON ec.subject_id=es2.id
    WHERE ec.id=#{courseId}
</select>

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

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

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

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

在Service模块的pom中

<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接口

//课程确认信息显示
getPublishCourseInfo(id) {
    return request({
        url: `/eduservice/course/getPublishCourseInfo/${id}`,
        method: 'get'
    })
}

2、引入接口

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

3、编写前端js

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

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>

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

在这里插入图片描述
1、编写Controller类

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

2、定义api接口

//课程最终发布
publishCourse(id) {
    return request({
        url: `/eduservice/course/publishCourse/${id}`,
        method: 'post'
    })
}

3、编写前端js

在views/edu/publish.vue中

publish() {
   this.$confirm('确认最终发布课程, 是否继续?', '提示', {
           confirmButtonText: '确定',
           cancelButtonText: '取消',
           type: 'warning'
       }).then(() => {//点击确定,删除成功
           //调用删除方法
           course.publishCourse(this.courseId)
           .then(response => {//删除成功
               //提示信息
               this.$message({
               type: 'success',
               message: '课程发布成功!'
               });
               //跳转到课程列表页面
               this.$router.push({ path: '/course/list' })
           }) 
       })//点击取消,发布失败
 }
}

四、课程列表显示

效果图

在这里插入图片描述
1、后端Controller类

@ApiOperation(value = "课程列表")
@GetMapping("getCourseList")
public R getCourseList(){
    List<EduCourse> list = courseService.list(null);
    return R.ok().data("list",list);
}

@ApiOperation(value = "分页查询课程列表")
@PostMapping("pageListCourse/{current}/{limit}")
public R pageListCourse(
        @ApiParam(name = "current", value = "当前页码", required = true)
        @PathVariable Long current,
        @ApiParam(name = "limit", value = "每页记录数", required = true)
        @PathVariable Long limit){
    //创建page对象
    Page<EduCourse> pageCourse =new Page<>(current,limit);

    //调用方法查询
    courseService.page(pageCourse,null);

    long total = pageCourse.getTotal();
    List<EduCourse> courseList = pageCourse.getRecords();

    return R.ok().data("total",total).data("rows",courseList);
}

//TODO 带条件的分页查询
@ApiOperation(value = "条件查询带分页课程列表")
@PostMapping("pageCourseCondition/{current}/{limit}")
public R pageCourseCondition(
        @ApiParam(name = "current", value = "当前页码", required = true)
        @PathVariable Long current,
        @ApiParam(name = "limit", value = "每页记录数", required = true)
        @PathVariable Long limit,
        @RequestBody(required = false) CourseQuery courseQuery){
    //创建page对象
    Page<EduCourse> pageCourse =new Page<>(current,limit);

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

    //组合条件查询
    String title = courseQuery.getTitle();
    String status = courseQuery.getStatus();

    //判断是否为空,不为空就拼接查询
    if (!StringUtils.isEmpty(title)) {
        wrapper.like("title",title);
    }
    if (!StringUtils.isEmpty(status)) {
        wrapper.eq("status",status);
    }

    //调用方法查询
    courseService.page(pageCourse,wrapper);

    long total = pageCourse.getTotal();
    List<EduCourse> courseList = pageCourse.getRecords();

    return R.ok().data("total",total).data("rows",courseList);
}

2、定义api接口

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

3、页面展示

<template>
  <div class="app-container">
    课程列表

    <!--查询表单-->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="courseQuery.title" placeholder="课程名称"/>
      </el-form-item>

      <el-form-item>
        <el-select v-model="courseQuery.status" clearable placeholder="课程状态">
          <el-option value="Normal" label="已发布"/>
          <el-option value="Draft" label="未发布"/>
        </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-table
      :data="list"
      border
      fit
      highlight-current-row>

      <el-table-column
        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="课程名称" />

      <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="180"/>

      <el-table-column prop="viewCount" label="浏览数量" width="70" />

      <el-table-column label="操作" width="200" 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="primary" size="mini" icon="el-icon-edit">编辑课程大纲息</el-button>
          </router-link>
          <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(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>

4、编写前端js

<script>
//引入调用teacher.js文件
import course from '@/api/edu/course'

export default {
    //写核心代码位置
    // data:{
    // },
    data() { //定义变量和初始值
        return {
          list:null,//查询之后接口返回集合
          page:1,//当前页
          limit:10,//每页记录数
          total:0,//总记录数
          courseQuery:{} //条件封装对象
        }
    },
    created() { //页面渲染之前执行,一般调用methods定义的方法
        //调用
        this.getList() 
    },
    methods:{
      getList(page = 1){
        this.page = page
        course.pageCourseCondition(this.page,this.limit,this.courseQuery)
            .then(response =>{
                this.list = response.data.rows
                this.total = response.data.total
            }) //请求成功
            .catch(error => {
              console.log(error)
            }) //请求失败
      },
      //课程列表的方法
      // getList() {
      //     course.getListCourse()
      //         .then(response =>{//请求成功
      //             //response接口返回的数据
      //             this.list = response.data.list
      //         }) 
      // },
      resetData() {//清空的方法
          //表单输入项数据清空
          this.courseQuery = {}
          //查询所有课程数据
          this.getList()
      }
 
  }
}
</script>

五、课程列表删除

删除课程,要把视频,小节,章节,描述,课程本身都删除。

1、后端Controller类

@ApiOperation(value = "删除课程")
@PostMapping("deleteCourse/{courseId}")
public R deleteCourse(@PathVariable String courseId){
    courseService.removeCourse(courseId);
    return R.ok();
}

2、后端service类

@Override
public void removeCourse(String courseId) {
    //1 根据课程id删除小节
    videoService.removeVideoByCourseId(courseId);

    //2 根据课程id删除章节
    chapterService.removeChapterByCourseId(courseId);

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

    //4 根据课程id删除课程本身
    int result = baseMapper.deleteById(courseId);
    if (result == 0){
        throw new GuliException(20001,"删除失败");
    }
}

3、定义api接口

//删除课程
deleteCourse(courseId) {
    return request({
        url: `/eduservice/course/deleteCourse/${courseId}`,
        method: 'post'
    })
},

4、编写前端js

removeDataById(id) {
 this.$confirm('此操作将永久删除课程, 是否继续?', '提示', {
       confirmButtonText: '确定',
       cancelButtonText: '取消',
       type: 'warning'
   }).then(() => {//点击确定,删除成功
       //调用删除方法
       course.deleteCourse(id)
       .then(response => {//删除成功
           //提示信息
           this.$message({
           type: 'success',
           message: '删除课程成功!'
           });
           //刷新页面
           this.getList()
       }) 
   })//点击取消,删除失败
},

六、阿里云视频点播服务

视频点播(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

对于控制台说明:

在这里插入图片描述

对于文档&SDK说明:

在这里插入图片描述

服务端:后端接口

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

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

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

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

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

1、获取视频播放地址

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

引入依赖

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

public class TestVod {

    public static void main(String[] args) throws Exception {
        //根据视频id获取视频播放地址
        //创建初始化对象
        DefaultAcsClient client = InitObject.initVodClient("<您的AccessKeyId>", "<您的AccessKeySecret>");

        //创建获取视频地址request和response
        GetPlayInfoRequest request = new GetPlayInfoRequest();
        GetPlayInfoResponse response = new GetPlayInfoResponse();

        //向request对象里面设置视频id
        request.setVideoId("视频ID");

        //调用初始化对象里面的方法,传递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");
    }
}

2、获取视频播放凭证

public static void main(String[] args) throws Exception {
    //根据视频id获取视频播放凭证
    //创建初始化对象
    DefaultAcsClient client = InitObject.initVodClient("LTAI4GAS6zW5Gh6amLaHJBLT", "A0ZKeYdnQw0eWE1hR7BLmq0SOR5OMA");

    //创建获取视频地址request和response
    GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
    GetVideoPlayAuthResponse response = new GetVideoPlayAuthResponse();

    //向request对象里面设置视频id
    request.setVideoId("c55d4cfcc36c47c5b7fd9f34e5367555");

    //调用初始化对象里面的方法,传递request,获取数据
    response = client.getAcsResponse(request);
    System.out.println("playauth:"+response.getPlayAuth());
}

3、上传视频到阿里云视频点播服务

public static void main(String[] args) throws Exception {
   //上传视频的方法
    String accessKeyId = "LTAI4GAS6zW5Gh6amLaHJBLT";
    String accessKeySecret = "A0ZKeYdnQw0eWE1hR7BLmq0SOR5OMA";

    String title = "6 - What If I Want to Move Faster";   //上传之后文件名称
    String fileName = "E:/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");
    } 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");
    }
}

4、视频上传

文档位置:
在这里插入图片描述
安装非开源的jar包

以 1.4.12 版本为例,步骤如下:

1.下载Java示例代码VODUploadDemo-java-1.4.13.zip开发包(包含示例代码和所需jar包), 见服务端上传SDK ;

2.将解压后lib目录下的所有jar文件拷贝至您的项目中;

3.SDK依赖的jar包版本说明

注意:以下列举出部分依赖jar包的版本,您可直接在您的项目中添加maven依赖,也可以将VODUploadDemo-java-1.4.13.zip包中的所有jar包引入您的项目中使用。其中,aliyun-java-vod-upload-1.4.13.jar 还未正式开源,请您直接引入jar包至您的项目中使用

步骤如下:

  • 引入上传视频,但是这个依赖不能在maven中央仓库中下载到,手动把依赖安装到本地仓库里面。
  • 使用maven命令安装

在本地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

引入依赖:

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

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

1、引入依赖

2、创建application配置文件

#服务端口
server.port=8003
#服务名
spring.application.name=service-vod

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

#阿里云 vod
#不同的服务器,地址不同
aliyun.oss.file.keyid=LTAI4GAS6zW5Gh6amLaHJBLT
aliyun.oss.file.keysecret=A0ZKeYdnQw0eWE1hR7BLmq0SOR5OMA

3、主启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//默认不去加载数据库配置
@ComponentScan(basePackages = {"com.kuang"})
public class VodApplication {

    public static void main(String[] args) {
        SpringApplication.run(VodApplication.class,args);
    }
}

4、编写Controller类

@Api(description = "阿里云视频上传")
@RestController
@RequestMapping("/eduvod/video")
@CrossOrigin
public class VodController {

    @Autowired
    private VodService vodService;

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

5、编写Service类

@Service
public class VodServiceImpl implements VodService {

    @Override
    public String uploadAlyiVideo(MultipartFile file) {
        try {
            //fileName:上传文件原始名称
            //01.mp4
            String fileName = file.getOriginalFilename();
            //title:上传之后显示名称
            String title = fileName.substring(0,fileName.lastIndexOf("."));
            //inputStream:上传文件输入流
            InputStream inputStream = file.getInputStream();

            UploadStreamRequest request = new UploadStreamRequest(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_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、编写工具类

@Component
public class ConstantVodUtils implements InitializingBean {

    @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;

    @Override
    public void afterPropertiesSet() throws Exception {
        ACCESS_KEY_ID = keyId;
        ACCESS_KEY_SECRET = keySecret;
    }
}

上面代码运行出现错误,上传大小问题
在这里插入图片描述
在application进行文件大小设置

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

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

1、整合上传组件

<el-form-item label="上传视频">
    <el-upload
        :on-success="handleVodUploadSuccess"
        :on-remove="handleVodRemove"
        :before-remove="beforeVodRemove"
        :on-exceed="handleUploadExceed"
        :file-list="fileList"
        :action="BASE_API+'/eduvod/video/uploadAlyiVideo'"
        :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>

2、数据定义

fileList: [],//上传文件列表
BASE_API: process.env.BASE_API // 接口API地址

3、方法定义

//上传视频成功调用的方法
handleVodUploadSuccess(response, file, fileList) {
     //上传视频id赋值
     this.video.videoSourceId = response.data.videoId
     //上传视频名称赋值
     this.video.videoOriginalName = file.name
 },
 handleUploadExceed() {
     this.$message.warning('想要重新上传视频,请先删除已上传的视频')
 },

4、出现问题及解决方法

(1)需要在nginx 配置8003 端口规则

location ~ /eduvod/ {
	proxy_pass http://localhost:8003;
}

(2)nginx支持上传文件大小限制
在这里插入图片描述
解决方法:在nginx配置文件中添加大小设置

在这里插入图片描述

5、删除视频后端接口

@ApiOperation(value = "根据视频id删除阿里云视频")
@DeleteMapping("removeAliyVideo/{id}")
public R removeAliyVideo(@PathVariable String id) {
    try{
        //初始化对象
        DefaultAcsClient client = InitVodClient.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET);
        //创建删除视频request对象
        DeleteVideoRequest request = new DeleteVideoRequest();
        //想request设置视频id
        request.setVideoIds(id);
        //调用初始化对象的方法实现删除
        client.getAcsResponse(request);
        return R.ok();
    }catch (Exception e){
        e.printStackTrace();
        throw new GuliException(20001,"删除视频失败");
    }
}

6、点击 X 删除上传文件

在这里插入图片描述
在api中定义接口

//删除视频
removeAliyVideo(id) {
    return request({
        url: `/eduvod/video/removeAliyVideo/${id}`,
        method: 'delete'
    })
}

页面调用

//点击确定调用的方法
handleVodRemove() {
    //调用接口的删除视频的方法
    video.deleteAliyunvod(this.video.videoSourceId)
        .then(response => {
            //提示信息
            this.$message({
                type: 'success',
                message: '删除视频成功!'
            });
            //把文件列表清空
            this.fileList = []
            //把video视频id和视频名称值清空
            //上传视频id赋值
            this.video.videoSourceId = ''
            //上传视频名称赋值
            this.video.videoOriginalName = ''
        })
},
//点击×调用这个方法
beforeVodRemove(file,fileList) {
    return this.$confirm(`确定移除 ${ file.name }?`);
},

如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 转发与重定向【面试题】

    请求转发与重定向 请求转发和重定向是 web 应用页面跳转的主要手段 xff0c 应用十分广泛 xff0c 所以我们一定要搞清楚他们的区别 1 请求转发 1 xff09 第一个 Servlet 接收到了浏览器端的请求 xff0c 进行了一定
  • 路径问题:相对路径与绝对路径

    1 提出问题 创建 Web 应用 Path xff0c 目录结构如图所示 在 a html 中有超链接 lt a href 61 34 b html 34 gt To b html lt a gt 如果先直接访问 a html xff0c
  • PyTorch:torch.Tensor.repeat()、expand()

    目录 1 torch Tensor repeat 2 torch Tensor expand 1 torch Tensor repeat 函数定义 xff1a repeat sizes Tensor 作用 xff1a 在指定的维度上重复这个
  • Cookie学习笔记

    1 cookie 简介 1 1 什么是 cookie cookie xff0c 有时我们也用其复数形式 cookies xff0c 是服务端保存在浏览器端的数据片段 以 key value 的形式进行保存 每次请求的时候 xff0c 请求头
  • mybatis中关于example类详解

    一 什么是example类 mybatis generator会为每个字段产生如上的Criterion xff0c 如果表的字段比较多 产生的Example类会十分庞大 理论上通过example类可以构造你想到的任何筛选条件 在mybati
  • springmvc实现文件上传与下载【单张及多张图片】

    一 springmvc实现文件上传的步骤 1 实现上传单张图片 1 导入pom 坐标 span class token comment lt 文件上传 gt span span class token tag span class toke
  • SpringBoot 搭建的个人博客

    介绍 blog是基于SpringBoot 搭建的个人博客 xff0c 响应式 前端技术 xff1a html css js jq bootstrap 后台技术 xff1a springboot thymeleaf mybatis mysql
  • SpringCloud(一)微服务概述

    文章目录 微服务概述什么是微服务微服务与微服务架构微服务的优缺点优点缺点 微服务的技术栈为什么选SpringCloud作为微服务架构选型依据当前各大IT公司的微服务架构各微服务的框架对比 SpringCloud入门概述SpringCloud
  • SpringCloud(二)入门案例之支付模块与订单模块的调用

    SpringCloud xff08 一 xff09 微服务概述 xff1a https blog csdn net weixin 45606067 article details 108481733 构建SpringCloud工程 概述 x
  • SpringCloud(三)Eureka服务注册中心

    文章目录 1 Eureka基础知识什么是服务治理什么是服务注册Eureka两大组件 2 Eureka介绍及原理理解介绍原理 3 单机版Eureka 构建步骤4 集群版Eureka 构建步骤Eureka集群原理说明EurekaServer集群
  • SpringCloud(四)zookeeper介绍及原理

    SpringCloud xff08 四 xff09 zookeeper介绍及原理 xff1a https blog csdn net weixin 45606067 article details 108499344 Zookeeper服务
  • docker 的安装 - 常用命令 - 应用部署

    文章目录 1 Docker简介什么是虚拟化什么是Docker容器与虚拟化比较Docker 组件1 Docker服务器与客户端2 Docker镜像与容器3 Register xff08 注册中心 xff09 2 Docker安装与启动安装Do
  • SpringCloud(六)Ribbon负载均衡服务调用

    Ribbon负载均衡 概述 是什么 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡工具 简单的说 xff0c Ribbon是Netflix发布的开源项目 xff0c 主要功能是提供客户端的
  • Python:map()函数使用详解

    1 函数定义 xff1a map function iterable 2 作用 xff1a 该函数通过接收一个函数function作为处理函数 xff0c 然后接收一个参数序列iterable xff0c 并使用处理函数对序列中的每个元素逐
  • SpringCloud(五)Consul服务注册与发现

    SpringCloud xff08 四 xff09 zookeeper介绍及原理 xff1a https blog csdn net weixin 45606067 article details 108538357 Consul简介 是什
  • SpringCloud(七)OpenFeign负载均衡服务调用

    1 概述 1 OpenFeign是什么 官网解释 xff1a https cloud spring io spring cloud static Hoxton SR1 reference htmlsingle spring cloud op
  • Zookeeper概述 | 安装部署(Windows和Linux)

    Zookeeper 一 Zokeeper 门 1 概述 Zookeeper是一个开源的分布式的 xff0c 为分布式应用提供协调服务的Apache项目 ZooKeeper is a centralized service for maint
  • Zookeeper内部原理

    Zookeeper概述 安装部署 xff08 Windows和Linux xff09 xff1a https blog csdn net weixin 45606067 article details 108619378 1 选举机制 面试
  • jsp和servlet的区别

    基本介绍 Servlet xff1a Servlet 是一种服务器端的Java应用程序 xff0c 具有独立于平台和协议的特性 xff0c 可以生成动态的Web页面 它担当客户请求 xff08 Web浏览器或其他HTTP客户程序 xff09
  • Session学习笔记

    1 session 简介 session 是我们 jsp 九大隐含对象的一个对象 session 称作域对象 xff0c 他的作用是保存一些信息 xff0c 而 session 这个域对象是一次会话期间使用同一个对象 所以这个对象可以用来保

随机推荐