在线教育之学习中心搭建

举报
tea_year 发表于 2025/10/31 15:09:35 2025/10/31
【摘要】 一、搭建学习中心前端腾讯课堂网学习中心提供学生在线学习的各各模块,上一章节测试的点播学习功能也属于学习中心的一部分,本章 节将实现学习中心点播学习的前端部分。之所以先实现前端部分,主要是因为要将video.js+vue.js集成,一部分精 力还是要放在技术研究。4.1 界面原型先看一下界面原型,如下图,最终的目标是在此页面使用video.js播放视频4.2 创建学习中心工程学习中心的用户是学...

一、搭建学习中心前端

腾讯课堂网学习中心提供学生在线学习的各各模块,上一章节测试的点播学习功能也属于学习中心的一部分,本章 节将实现学习中心点播学习的前端部分。之所以先实现前端部分,主要是因为要将video.js+vue.js集成,一部分精 力还是要放在技术研究。

4.1 界面原型

先看一下界面原型,如下图,最终的目标是在此页面使用video.js播放视频

image-20210114172916665.png


4.2 创建学习中心工程

学习中心的用户是学生,为了便于系统维护和扩展,单独创建学习中心工程:

  1. 从资料目录拷贝yh-ui-pc-leanring.zip 并解压到yh-ui-pc-leanring目录。

  2. 使用webstorm创建打开yh-ui-pc-leanring目录

  3. 进入yh-ui-pc-leanring目录,执行cnpm install,将根据package.json的依赖配置远程下载依赖的 js 包。创建完成,yh-ui-pc-leanring工程如下:

工程中没有依赖库,需要cnpm install下载

image-20210114172952445.png


4.2.1 配置域名

学习中心的二级域名为ucenter.lxw.com,我们在nginx中配置ucenter虚拟主机

#腾讯课堂网用户中心
server {
   listen       80;
   server_name ucenter.lxw.com;
   #个人中心
   location / { 
       proxy_pass http://ucenter_server_pool;   
  }   
}
#前端ucenter
upstream ucenter_server_pool{
   #server 127.0.0.1:7081 weight=10;
   server 127.0.0.1:13000 weight=10;
}


4.2.2 访问

启动工程,看到下边的界面说明本工程创建完成:

image-20210114173051429.png


4.3 调试视频播放页面

使用vue-video-player组件将video.js集成到vue.js中,本项目使用vue-video-player实现video.js播放。 组件地址:https://github.com/surmon-china/vue-video-player

上面的 yh-ui-pc-learning工程已经添加vue-video-player组件,我们在vue页面直接使用即可。

前边我们已经测试通过 video.js,下面我们直接在vue页面中使用vue-video-player完成视频播放。 导入learning_video.vue页面到course 模块下。

配置路由

import learning_video from '@/module/course/page/learning_video.vue';
{
   path: '/learning/:courseId/:chapter',
       component: learning_video,
           name: '录播视频学习',
               hidden: false,
                   iconCls: 'el‐icon‐document'
}

预览效果:

请求:http://ucenter.lxw.com/#/learning/1/2

第一个参数:courseId,课程id,这里是测试页面效果随便输入一个ID即可,这里输入1 第二个参数:chapter,课程计划id,这里是测试页面效果随便输入一个ID即可,这里输入2

image-20210114173140489.png




二、媒资管理

前边章节完成在线视频播放,如何实现点击课程计划播放视频呢,课程视频如何管理呢? 本节开始将对课程视频进行管理。


5.1需求分析

媒资管理系统是每个在线教育平台所必须具备的,百度百科对它的定义如下

image-20210114173210110.png


每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。 目前媒资管理的主要管理对象是课程录播视频,包括:媒资文件的查询、视频上传、视频删除、视频处理等。 媒资查询:教学机构查询自己所拥有的媒体文件。

视频上传:将用户线下录制的教学视频上传到媒资系统。 视频处理:视频上传成功,系统自动对视频进行编码处理。 视频删除 :如果该视频已不再使用,可以从媒资系统删除。下边是媒资系统与其它系统的交互情况


image-20210114173229364.png

1、上传媒资文件 前端/客户端请求媒资系统上传文件。 文件上传成功将文件存储到媒资服务器,将文件信息存储到数据库。 2、使用媒资 课程管理请求媒资系统查询媒资信息,将课程计划与媒资信息对应、存储。 3、视频播放 用户进入学习中心请求学习服务学习在线播放视频。 学习服务校验用户资格通过后请求媒资系统获取视频地址




5.2 开发环境

5.2.1 创建媒资数据库

媒资mongo数据库:yh_media下建立集合media_file

  1. 媒资文件信息

    @Data
    @ToString
    @Document(collection = "media_file")
    public class MediaFile {
       /*
       文件id、名称、大小、文件类型、文件状态(未上传、上传完成、上传失败)、上传时间、视频处理方式、视频处
    理状态、hls_m3u8,hls_ts_list、课程视频信息(课程id、章节id)
     */
       @Id
       //文件id
       private String fileId;
       //文件名称
       private String fileName;
       //文件原始名称
       private String fileOriginalName;
       //文件路径
       private String filePath;
       //文件url
       private String fileUrl;
       //文件类型
       private String fileType;
       //mimetype
       private String mimeType;
       //文件大小
       private Long fileSize;
       //文件状态
       private String fileStatus;
       //上传时间
       private Date uploadTime;
    }
  2. 创建yh_media数据库

    媒资系统使用mongodb数据库存储媒资信息


5.2.2 创建媒资服务工程

媒资管理的相关功能单独在媒资服务中开发,下边创建媒资服务工程(yh-service-manage- media)。媒资服务的配置与cms类似,导入 “资料”--》yh-service-manage-media工程,工程结构

image-20210114173728054.png


5.3上传文件

5.3.1 断点续传解决方案

通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件的上传要求。http协议本身对上传文件大 小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了,电断了没 有上传完成,需要客户重新上传,这是致命的,所以对于大文件上传的要求最基本的是断点续传。 什么是断点续传:

引用百度百科:断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载,断点续传可以提高节省操作时间,提高用户体验性。

如下图:

image-20210114173807707.png

上传流程如下: 1、上传前先把文件分成块 2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传 3、各分块上传完成最后合并文件

文件下载则同理。


5.3.2 文件分块与合并

为了更好的理解文件分块上传的原理,下边用java代码测试文件的分块与合并。


5.3.2.1文件分块

文件分块的流程如下:

1、获取源文件长度 2、根据设定的分块文件的大小计算出块数 3、从源文件读数据依次向每一个块文件写数据

     //测试文件分块方法
   @Test
   public void testChunk() throws IOException {
       File sourceFile = new File("F:/develop/ffmpeg/mybatis.mp4");

       String chunkPath = "F:/develop/ffmpeg/chunk/";
       File chunkFolder = new File(chunkPath);
       if(!chunkFolder.exists()){
           chunkFolder.mkdirs();
      }
       //分块大小
       long chunkSize = 512*1024*1;
       //分块数量
       long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize );
       if(chunkNum<=0){
           chunkNum = 1;
      }
       //缓冲区大小
       byte[] b = new byte[1024];
       //使用RandomAccessFile访问文件
       RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r");
       //分块
       for(int i=0;i<chunkNum;i++){
           //创建分块文件
           File file = new File(chunkPath+i);//F:/develop/ffmpeg/chunk/0
           boolean newFile = file.createNewFile();
           if(newFile){
               //向分块文件中写数据
               RandomAccessFile raf_write = new RandomAccessFile(file, "rw");
               int len = -1;
               while((len = raf_read.read(b))!= -1){
                   raf_write.write(b,0,len);
                   if(file.length()>chunkSize){
                       break;
                  }
              }
               raf_write.close();
          }
      }
       raf_read.close();
  }


5.3.2.2文件合并

文件合并流程: 1、找到要合并的文件并按文件合并的先后进行排序。 2、创建合并文件 3、依次从合并的文件中读取数据向合并文件写入数

//测试文件合并方法
@Test
public void testMerge() throws IOException {
   //块文件目录
   File chunkFolder = new File("F:/develop/ffmpeg/chunk/"); 
   //合并文件
   File mergeFile = new File("F:/develop/ffmpeg/1.mp4");
   if(mergeFile.exists()){
       mergeFile.delete();
  }
   //创建新的合并文件
   mergeFile.createNewFile();
   //用于写文件
   RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw");
   //指针指向文件顶端
   raf_write.seek(0);
   //缓冲区
   byte[] b = new byte[1024];
   //分块列表
   File[] fileArray = chunkFolder.listFiles();
   // 转成集合,便于排序
   List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
   // 从小到大排序
   Collections.sort(fileList, new Comparator<File>() {
       @Override
       public int compare(File o1, File o2) {
           if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
               return ‐1;
          }
           return 1;
      }
  });
   //合并文件
   for(File chunkFile:fileList){
       RandomAccessFile raf_read = new RandomAccessFile(chunkFile,"rw");
       int len = ‐1;
       while((len=raf_read.read(b))!=‐1){
           raf_write.write(b,0,len);
      }
       raf_read.close();
  }
   raf_write.close();
}


5.3.3 前端页面

上传文件的页面内容参考:“资料”--》upload.vue文件

5.3.3.1 WebUploader介绍

如何在web页面实现断点续传?

常见的方案有: 1、通过Flash上传,比如SWFupload、Uploadify。

2、安装浏览器插件,变相的pc客户端,用的比较少。 3、Html5

随着 html5 的流行,本项目采用 Html5 完成文件分块上传。


本项目使用WebUploader完成大文件上传功能的开发,WebUploader官网地址: http://fex.baidu.com/webuploader/

image-20210114174137216.png


特性如下

image-20210114174153049.png


使用 WebUploader 上传流程如下


image-20210114174220627.png


6.3.3.1 钩子方法

在 webuploader 中提供很多钩子方法,下边列出一些重要的

image-20210114174242972.png


本项目使用如下钩子方法:

  1. before-send-file 在开始对文件分块儿之前调用,可以做一些上传文件前的准备工作,比如检查文件目录是否创建完成等。

  2. before-send 在上传文件分块之前调用此方法,可以请求服务端检查分块是否存在,如果已存在则此分块儿不再上传。

  3. after-send-file 在所有分块上传完成后触发,可以请求服务端合并分块文件。

    注册钩子方法源代码

    WebUploader.Uploader.register({
       "before‐send‐file":"beforeSendFile",
       "before‐send":"beforeSend",
       "after‐send‐file":"afterSendFile"
    }


5.3.3.2 构建WebUploader

使用webUploader前需要创建webUploader对象。 指定上传分块的地址:/api/media/upload/uploadchunk

// 创建uploader对象,配置参数
this.uploader = WebUploader.create({
       swf:"/static/plugins/webuploader/dist/Uploader.swf",
       //上传文件的flash文件,浏览器不支持h5时启动
       flash
       server:"/api/media/upload/uploadchunk",//上传分块的服务端地址,注意跨域问题
       fileVal:"file",//文件上传域的name
       pick:"#picker",//指定选择文件的按钮容器
       auto:false,//手动触发上传
       disableGlobalDnd:true,//禁掉整个页面的拖拽功能
       chunked:true,// 是否分块上传
       chunkSize:1*1024*1024, // 分块大小(默认5M)
       threads:3, // 开启多个线程(默认3个)
       prepareNextFile:true// 允许在文件传输时提前把下一个文件准备好
})


5.3.3.3 before-send-file

文件开始上传前前端请求服务端准备上传工作。 参考源代码如下

type:"POST",
   url:"/api/media/upload/register",
       data:{
           // 文件唯一表示
           fileMd5:this.fileMd5,
               fileName: file.name,
                   fileSize:file.size,
                       mimetype:file.type,
                           fileExt:file.ext
      }


5.3.3.4 before-send

上传分块前前端请求服务端校验分块是否存在。 参考源代码如下

type:"POST",
   url:"/api/media/upload/checkchunk",
       data:{
           // 文件唯一表示
           fileMd5:this.fileMd5,
               // 当前分块下标
               chunk:block.chunk,
                   // 当前分块大小
                   chunkSize:block.end‐block.start
      }


5.3.3.5 after-send-file

在所有分块上传完成后触发,可以请求服务端合并分块文件

参考代码如下

type:"POST",
   url:"/api/media/upload/mergechunks",
       data:{
           fileMd5:this.fileMd5,
               fileName: file.name,
                   fileSize:file.size,
                       mimetype:file.type,
                           fileExt:file.ext
      }


5.3.3.6 页面效果

image-20210114174544369.png


5.3.4 Api 接口

定义文件上传的Api接口,此接收是前端WebUploader调用服务端的接口。 编写此接口需要参数前端WebUploader应用代码

@Api(value = "媒资管理接口",description = "媒资管理接口,提供文件上传,文件处理等接口")
public interface MediaUploadControllerApi {
  @ApiOperation("文件上传注册")
       public ResponseResult register(String fileMd5,
               String fileName,
               Long fileSize,
               String mimetype,
               String fileExt);

       @ApiOperation("分块检查")
       public CheckChunkResult checkChunk(String fileMd5,
               Integer chunk,
               Integer chunkSize);

       @ApiOperation("上传分块")
       public ResponseResult uploadChunk(MultipartFile file,
                                         Integer chunk,
                                         String fileMd5);

       @ApiOperation("合并文件")
       public ResponseResult mergeChunks(String fileMd5,
               String fileName,
               Long fileSize,
               String mimetype,
               String fileExt);

  }


5.3.5媒资服务端编写

5.3.5.1 业务流程

服务端需要实现如下功能:

1、上传前检查上传环境 检查文件是否上传,已上传则直接返回。 检查文件上传路径是否存在,不存在则创建。

2、分块检查 检查分块文件是否上传,已上传则返回true。 未上传则检查上传路径是否存在,不存在则创建。

3、分块上传 将分块文件上传到指定的路径。

4、合并分块 将所有分块文件合并为一个文件。 在数据库记录文件信息。



5.3.5.2 上传注册

由于上传过程复杂,开发时按业务流程分别实现。

1、配置 application.yml配置上传文件的路径

yh‐service‐manage‐media:
 upload‐location: F:/develop/video/


2、媒资文件管理Dao

public interface MediaFileRepository extends MongoRepository<MediaFile,String> {
}


3、Service

功能: 1)检查上传文件是否存在 2)创建文件目录

@Service
public class MediaUploadService {
   private final static Logger LOGGER = LoggerFactory.getLogger(MediaUploadController.class);
   @Autowired
   MediaFileRepository mediaFileRepository;
   //上传文件根目录
   @Value("${yh‐service‐manage‐media.upload‐location}")
   String uploadPath;
   /**
* 根据文件md5得到文件路径
* 规则:
* 一级目录:md5的第一个字符
* 二级目录:md5的第二个字符
* 三级目录:md5
* 文件名:md5+文件扩展名
* @param fileMd5 文件md5值
* @param fileExt 文件扩展名
* @return 文件路径
*/
   private String getFilePath(String fileMd5,String fileExt){
       String filePath = uploadPath+fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + 
           "/" + fileMd5 + "/" + fileMd5 + "." + fileExt;
       return filePath;
  }
   //得到文件目录相对路径,路径中去掉根目录
   private String getFileFolderRelativePath(String fileMd5,String fileExt){
       String filePath = fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + 
           fileMd5 + "/";
       return filePath;
  }
   //得到文件所在目录
   private String getFileFolderPath(String fileMd5){
       String fileFolderPath = uploadPath+ fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 
                                                                                             2) + "/" + fileMd5 + "/" ;
       return fileFolderPath;
  }
   //创建文件目录
   private boolean createFileFold(String fileMd5){
       //创建上传文件目录
       String fileFolderPath = getFileFolderPath(fileMd5);
       File fileFolder = new File(fileFolderPath);
       if (!fileFolder.exists()) {
           //创建文件夹
           boolean mkdirs = fileFolder.mkdirs();
           return mkdirs;
      }
       return true;
  }
   //文件上传注册
   public ResponseResult register(String fileMd5, String fileName, String fileSize, String 
                                  mimetype, String fileExt) {
       //检查文件是否上传
       //1、得到文件的路径
       String filePath = getFilePath(fileMd5, fileExt);
       File file = new File(filePath);
       //2、查询数据库文件是否存在
       Optional<MediaFile> optional = mediaFileRepository.findById(fileMd5);
       //文件存在直接返回
       if(file.exists() && optional.isPresent()){
           ExceptionCast.cast(MediaCode.UPLOAD_FILE_REGISTER_EXIST);
      }
       boolean fileFold = createFileFold(fileMd5);
       if(!fileFold){
           //上传文件目录创建失败
           ExceptionCast.cast(MediaCode.UPLOAD_FILE_REGISTER_CREATEFOLDER_FAIL);
      }
       return new ResponseResult(CommonCode.SUCCESS);
  }
}


5.3.5.3 分块检查

在Service 中定义分块检查方法:

//得到块文件所在目录
private String getChunkFileFolderPath(String fileMd5){
   String fileChunkFolderPath = getFileFolderPath(fileMd5) +"/" + "chunks" + "/";  
   return fileChunkFolderPath;  
}
//检查块文件
public CheckChunkResult checkchunk(String fileMd5, String chunk, String chunkSize) {
   //得到块文件所在路径
   String chunkfileFolderPath = getChunkFileFolderPath(fileMd5);
   //块文件的文件名称以1,2,3..序号命名,没有扩展名
   File chunkFile = new File(chunkfileFolderPath+chunk);
   if(chunkFile.exists()){
       return new CheckChunkResult(MediaCode.CHUNK_FILE_EXIST_CHECK,true);
  }else{
       return new CheckChunkResult(MediaCode.CHUNK_FILE_EXIST_CHECK,false);
  }
}


5.3.5.4 上传分块

在Service 中定义分块上传分块方法

//块文件上传
public ResponseResult uploadchunk(MultipartFile file, String fileMd5, String chunk) {
   if(file == null){
       ExceptionCast.cast(MediaCode.UPLOAD_FILE_REGISTER_ISNULL);
  }
   //创建块文件目录
   boolean fileFold = createChunkFileFolder(fileMd5);
   //块文件
   File chunkfile = new File(getChunkFileFolderPath(fileMd5) + chunk);
   //上传的块文件
   InputStream inputStream= null;
   FileOutputStream outputStream = null;
   try {
       inputStream = file.getInputStream();
       outputStream = new FileOutputStream(chunkfile);
       IOUtils.copy(inputStream,outputStream);
  } catch (Exception e) {
       e.printStackTrace();
       LOGGER.error("upload chunk file fail:{}",e.getMessage());
       ExceptionCast.cast(MediaCode.CHUNK_FILE_UPLOAD_FAIL);
  }finally {
       try {
           inputStream.close();
      } catch (IOException e) {
           e.printStackTrace();
      }
       try {
           outputStream.close();
      } catch (IOException e) {
           e.printStackTrace();
      }
  }
   return new ResponseResult(CommonCode.SUCCESS);
}
//创建块文件目录
private boolean createChunkFileFolder(String fileMd5){
   //创建上传文件目录
   String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
   File chunkFileFolder = new File(chunkFileFolderPath);
   if (!chunkFileFolder.exists()) {
       //创建文件夹
       boolean mkdirs = chunkFileFolder.mkdirs();
       return mkdirs;
  }
   return true;
}


5.3.5.5 合并分块

在Service 中定义分块合并分块方法,功能如下: 1)将块文件合并

2)校验文件md5是否正确 3)向Mongodb写入文件信息


//合并块文件
public ResponseResult mergechunks(String fileMd5, String fileName, Long fileSize, String 
                                 mimetype, String fileExt) {
   //获取块文件的路径
   String chunkfileFolderPath = getChunkFileFolderPath(fileMd5);
   File chunkfileFolder = new File(chunkfileFolderPath);
   if(!chunkfileFolder.exists()){
       chunkfileFolder.mkdirs();
  }
   //合并文件路径
   File mergeFile = new File(getFilePath(fileMd5,fileExt));
   //创建合并文件
   //合并文件存在先删除再创建
   if(mergeFile.exists()){
       mergeFile.delete();
  }
   boolean newFile = false;
   try {
       newFile = mergeFile.createNewFile();
  } catch (IOException e) {
       e.printStackTrace();
       LOGGER.error("mergechunks..create mergeFile fail:{}",e.getMessage());
  }
   if(!newFile){
       ExceptionCast.cast(MediaCode.MERGE_FILE_CREATEFAIL);
  }
   //获取块文件,此列表是已经排好序的列表
   List<File> chunkFiles = getChunkFiles(chunkfileFolder);
   //合并文件
   mergeFile = mergeFile(mergeFile, chunkFiles);
   if(mergeFile == null){
       ExceptionCast.cast(MediaCode.MERGE_FILE_FAIL);
  }
   //校验文件
   boolean checkResult = this.checkFileMd5(mergeFile, fileMd5);
   if(!checkResult){
       ExceptionCast.cast(MediaCode.MERGE_FILE_CHECKFAIL);
  }
   //将文件信息保存到数据库
   MediaFile mediaFile = new MediaFile();
   mediaFile.setFileId(fileMd5);
   mediaFile.setFileName(fileMd5+"."+fileExt);
   mediaFile.setFileOriginalName(fileName);
   //文件路径保存相对路径
   mediaFile.setFilePath(getFileFolderRelativePath(fileMd5,fileExt));
   mediaFile.setFileSize(fileSize);
   mediaFile.setUploadTime(new Date());
   mediaFile.setMimeType(mimetype);
   mediaFile.setFileType(fileExt);
   //状态为上传成功
   mediaFile.setFileStatus("301002");
   MediaFile save = mediaFileDao.save(mediaFile);
   return new ResponseResult(CommonCode.SUCCESS);
}
//校验文件的md5值
private boolean checkFileMd5(File mergeFile,String md5){
   if(mergeFile == null || StringUtils.isEmpty(md5)){
       return false;
  }
   //进行md5校验
   FileInputStream mergeFileInputstream = null;
   try {
       mergeFileInputstream = new FileInputStream(mergeFile);
       //得到文件的md5
       String  mergeFileMd5 = DigestUtils.md5Hex(mergeFileInputstream);
       //比较md5
       if(md5.equalsIgnoreCase(mergeFileMd5)){
           return true;
      }
  } catch (Exception e) {
       e.printStackTrace();
       LOGGER.error("checkFileMd5 error,file is:{},md5 is:                     {}",
                    mergeFile.getAbsoluteFile(),md5);
  }finally{
       try {
           mergeFileInputstream.close();
      } catch (IOException e) {
           e.printStackTrace();
      }
  }
   return false;
}
//获取所有块文件
private List<File> getChunkFiles(File chunkfileFolder){
   //获取路径下的所有块文件
   File[] chunkFiles = chunkfileFolder.listFiles();
   //将文件数组转成list,并排序
   List<File> chunkFileList = new ArrayList<File>();
   chunkFileList.addAll(Arrays.asList(chunkFiles));
   //排序
   Collections.sort(chunkFileList, new Comparator<File>() {
       @Override
       public int compare(File o1, File o2) {
           if(Integer.parseInt(o1.getName())>Integer.parseInt(o2.getName())){
               return 1;
          }
           return ‐1;
      }
  });
   return chunkFileList;
}
//合并文件
private File mergeFile(File mergeFile,List<File> chunkFiles){
   try {
       //创建写文件对象
       RandomAccessFile raf_write = new RandomAccessFile(mergeFile,"rw");
       //遍历分块文件开始合并
       //读取文件缓冲区
       byte[] b = new byte[1024];
       for(File chunkFile:chunkFiles){
           RandomAccessFile raf_read = new RandomAccessFile(chunkFile,"r");
           int len = ‐1;
           //读取分块文件
           while((len = raf_read.read(b))!=‐1){
               //向合并文件中写数据
               raf_write.write(b,0,len);
          }
           raf_read.close();
      }
       raf_write.close();
  } catch (Exception e) {
       e.printStackTrace();
       LOGGER.error("merge file error:{}",e.getMessage());
       return null;
  }
   return mergeFile;
}


5.3.5.6 Controller

@RestController
@RequestMapping("/media/upload")
public class MediaUploadController implements MediaUploadControllerApi {
   @Autowired
   MediaUploadService mediaUploadService;
   @Override
   @PostMapping("/register")
   public ResponseResult register(
       @RequestParam("fileMd5") String fileMd5, 
       @RequestParam("fileName") String fileName, 
       @RequestParam("fileSize") Long fileSize, 
       @RequestParam("mimetype") String mimetype, 
@RequestParam("fileExt") String fileExt) {
       
       return mediaUploadService.register(fileMd5,fileName,fileSize,mimetype,fileExt);
  }
   
   @Override
   @PostMapping("/checkchunk")
   public CheckChunkResult checkchunk(
       @RequestParam("fileMd5") String fileMd5,           
       @RequestParam("chunk") Integer chunk, 
       @RequestParam("chunkSize") Integer chunkSize) {
       
       return mediaUploadService.checkchunk(fileMd5,chunk,chunkSize);
  }
   
   
   @Override
   @PostMapping("/uploadchunk")
   public ResponseResult uploadchunk(
       @RequestParam("file") MultipartFile file, 
       @RequestParam("fileMd5") String fileMd5, 
       @RequestParam("chunk") Integer chunk) {
       
       return mediaUploadService.uploadchunk(file,fileMd5,chunk);
  }
   
   
   @Override
   @PostMapping("/mergechunks")
   public ResponseResult mergechunks(
       @RequestParam("fileMd5") String fileMd5,           
       @RequestParam("fileName") String fileName, 
       @RequestParam("fileSize") Long fileSize,                   
       @RequestParam("mimetype") String mimetype, 
       @RequestParam("fileExt") String fileExt) {
       
       return mediaUploadService.mergechunks(fileMd5,fileName,fileSize,mimetype,fileExt);
  }
}

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。