49677 字
约 165 分钟
47
appendix_E
无标签

附录E 媒资服务模块源码详解

模块概览(面向 0 基础读者):

  • 实现文件分片上传、合并校验、MinIO 存储与视频转码。
  • 利用 XXL-Job 异步转码,结合 Redis、数据库跟踪处理进度。
  • 向内容、学习等模块提供媒资绑定与访问接口。

核心目录:

  • xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/media/api
  • xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service
  • xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/jobhandler
  • xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper
  • xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model

文件:xuecheng-plus-media/api/main/com/xuecheng/media/api/BigFilesController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestParam; // 导入 RequestParam 类
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 类
import org.springframework.web.multipart.MultipartFile; // 导入 MultipartFile 类

import java.io.File; // 导入 File 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 上传视频 // 保留原作者写的块注释
 * @date 2023/2/18 10:34 // 保留原作者写的块注释
 */ // 保留原作者写的块注释

@Api(value = "大文件上传接口", tags = "大文件上传接口") // 使用注解 @Api(value = "大文件上传接口", tags = "大文件上传接口")
@RestController // 使用注解 @RestController
public class BigFilesController { // 定义 class BigFilesController

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句


    @ApiOperation(value = "文件上传前检查文件") // 使用注解 @ApiOperation(value = "文件上传前检查文件")
    @PostMapping("/upload/checkfile") // 使用注解 @PostMapping("/upload/checkfile")
    public RestResponse<Boolean> checkfile( // 代码逻辑
            @RequestParam("fileMd5") String fileMd5 // 使用注解 @RequestParam("fileMd5") String fileMd5
    ) throws Exception { // 代码逻辑
        RestResponse<Boolean> booleanRestResponse = mediaFileService.checkFile(fileMd5); // 把 mediaFileService.checkFile(fileMd5) 赋值给 booleanRestResponse
        return booleanRestResponse; // 返回 booleanRestResponse
    } // 代码块结束


    @ApiOperation(value = "分块文件上传前的检测") // 使用注解 @ApiOperation(value = "分块文件上传前的检测")
    @PostMapping("/upload/checkchunk") // 使用注解 @PostMapping("/upload/checkchunk")
    public RestResponse<Boolean> checkchunk(@RequestParam("fileMd5") String fileMd5, // 代码逻辑
                                            @RequestParam("chunk") int chunk) throws Exception { // 使用注解 @RequestParam("chunk") int chunk) throws Exception {
        RestResponse<Boolean> booleanRestResponse = mediaFileService.checkChunk(fileMd5,chunk); // 把 mediaFileService.checkChunk(fileMd5,chunk) 赋值给 booleanRestResponse
        return booleanRestResponse; // 返回 booleanRestResponse
    } // 代码块结束

    @ApiOperation(value = "上传分块文件") // 使用注解 @ApiOperation(value = "上传分块文件")
    @PostMapping("/upload/uploadchunk") // 使用注解 @PostMapping("/upload/uploadchunk")
    public RestResponse uploadchunk(@RequestParam("file") MultipartFile file, // 代码逻辑
                                    @RequestParam("fileMd5") String fileMd5, // 使用注解 @RequestParam("fileMd5") String fileMd5,
                                    @RequestParam("chunk") int chunk) throws Exception { // 使用注解 @RequestParam("chunk") int chunk) throws Exception {

        //创建一个临时文件 // 保留原作者写的行内注释
        File tempFile = File.createTempFile("minio", ".temp"); // 把 File.createTempFile("minio", ".temp") 赋值给 tempFile
        file.transferTo(tempFile); // 执行语句
        //文件路径 // 保留原作者写的行内注释
        String localFilePath = tempFile.getAbsolutePath(); // 把 tempFile.getAbsolutePath() 的返回值赋给 localFilePath

        RestResponse restResponse = mediaFileService.uploadChunk(fileMd5, chunk, localFilePath); // 把 mediaFileService.uploadChunk(fileMd5, chunk, localFilePath) 赋值给 restResponse

        return restResponse; // 返回 restResponse
    } // 代码块结束

    @ApiOperation(value = "合并文件") // 使用注解 @ApiOperation(value = "合并文件")
    @PostMapping("/upload/mergechunks") // 使用注解 @PostMapping("/upload/mergechunks")
    public RestResponse mergechunks(@RequestParam("fileMd5") String fileMd5, // 代码逻辑
                                    @RequestParam("fileName") String fileName, // 使用注解 @RequestParam("fileName") String fileName,
                                    @RequestParam("chunkTotal") int chunkTotal) throws Exception { // 使用注解 @RequestParam("chunkTotal") int chunkTotal) throws Exception {
        Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
        //文件信息对象 // 保留原作者写的行内注释
        UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto(); // 创建 UploadFileParamsDto 对象并赋值给 uploadFileParamsDto
        uploadFileParamsDto.setFilename(fileName); // 执行语句
        uploadFileParamsDto.setTags("视频文件"); // 执行语句
        uploadFileParamsDto.setFileType("001002"); // 执行语句
        RestResponse restResponse = mediaFileService.mergechunks(1232141425L, fileMd5, chunkTotal, uploadFileParamsDto); // 把 mediaFileService.mergechunks(1232141425L, fileMd5, chunkTotal, uploadFileParamsDto) 赋值给 restResponse
        return restResponse; // 返回 restResponse

    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/api/main/com/xuecheng/media/api/MediaFilesController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.http.MediaType; // 导入 MediaType 类
import org.springframework.web.bind.annotation.*; // 导入 * 类
import org.springframework.web.multipart.MultipartFile; // 导入 MultipartFile 类

import java.io.File; // 导入 File 类
import java.io.IOException; // 导入 IOException 类

/** // 保留原作者写的块注释
 * @description 媒资文件管理接口 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/9/6 11:29 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 @Api(value = "媒资文件管理接口",tags = "媒资文件管理接口") // 使用注解 @Api(value = "媒资文件管理接口",tags = "媒资文件管理接口")
 @RestController // 使用注解 @RestController
public class MediaFilesController { // 定义 class MediaFilesController


  @Autowired // 使用注解 @Autowired
  MediaFileService mediaFileService; // 执行语句


 @ApiOperation("媒资列表查询接口") // 使用注解 @ApiOperation("媒资列表查询接口")
 @PostMapping("/files") // 使用注解 @PostMapping("/files")
 public PageResult<MediaFiles> list(PageParams pageParams, @RequestBody QueryMediaParamsDto queryMediaParamsDto){ // 定义方法 list(...)
  Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
  return mediaFileService.queryMediaFiels(companyId,pageParams,queryMediaParamsDto); // 返回 mediaFileService.queryMediaFiels(companyId,pageParams,queryMediaParamsDto)

 } // 代码块结束

 @ApiOperation("上传图片") // 使用注解 @ApiOperation("上传图片")
 @RequestMapping(value = "/upload/coursefile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE) // 使用注解 @RequestMapping(value = "/upload/coursefile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public UploadFileResultDto upload(@RequestPart("filedata")MultipartFile filedata, // 代码逻辑
                                  @RequestParam(value= "objectName",required=false) String objectName) throws IOException { // 使用注解 @RequestParam(value= "objectName",required=false) String objectName) throws IOException {

    //准备上传文件的信息 // 保留原作者写的行内注释
     UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto(); // 创建 UploadFileParamsDto 对象并赋值给 uploadFileParamsDto
     //原始文件名称 // 保留原作者写的行内注释
     uploadFileParamsDto.setFilename(filedata.getOriginalFilename()); // 执行语句
     //文件大小 // 保留原作者写的行内注释
     uploadFileParamsDto.setFileSize(filedata.getSize()); // 执行语句
     //文件类型 // 保留原作者写的行内注释
     uploadFileParamsDto.setFileType("001001"); // 执行语句
     //创建一个临时文件 // 保留原作者写的行内注释
     File tempFile = File.createTempFile("minio", ".temp"); // 把 File.createTempFile("minio", ".temp") 赋值给 tempFile
     filedata.transferTo(tempFile); // 执行语句
     Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
    //文件路径 // 保留原作者写的行内注释
     String localFilePath = tempFile.getAbsolutePath(); // 把 tempFile.getAbsolutePath() 的返回值赋给 localFilePath

     //调用service上传图片 // 保留原作者写的行内注释
     UploadFileResultDto uploadFileResultDto = mediaFileService.uploadFile(companyId, uploadFileParamsDto, localFilePath,objectName); // 把 mediaFileService.uploadFile(companyId, uploadFileParamsDto, localFilePath,objectName) 赋值给 uploadFileResultDto

     return uploadFileResultDto; // 返回 uploadFileResultDto
 } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/api/main/com/xuecheng/media/api/MediaOpenController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.apache.commons.lang3.StringUtils; // 导入 StringUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 类
import org.springframework.web.bind.annotation.PathVariable; // 导入 PathVariable 类
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 类
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/21 10:35 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
// 视频播放页面接口 // 保留原作者写的行内注释
@Api(value = "媒资文件管理接口", tags = "媒资文件管理接口") // 使用注解 @Api(value = "媒资文件管理接口", tags = "媒资文件管理接口")
@RestController // 使用注解 @RestController
@RequestMapping("/open") // 使用注解 @RequestMapping("/open")
public class MediaOpenController { // 定义 class MediaOpenController

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句

    @ApiOperation("预览文件") // 使用注解 @ApiOperation("预览文件")
    @GetMapping("/preview/{mediaId}") // 使用注解 @GetMapping("/preview/{mediaId}")
    public RestResponse<String> getPlayUrlByMediaId(@PathVariable String mediaId) { // 定义方法 getPlayUrlByMediaId(...)
        //查询媒资文件信息 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFileService.getFileById(mediaId); // 把 mediaFileService.getFileById(mediaId) 赋值给 mediaFiles

        if (mediaFiles == null) { // 定义方法 方法(...)
            return RestResponse.validfail("找不到视频"); // 返回 RestResponse.validfail("找不到视频")
        } // 代码块结束
        //取出视频播放地址 // 保留原作者写的行内注释
        String url = mediaFiles.getUrl(); // 把 mediaFiles.getUrl() 的返回值赋给 url
        if (StringUtils.isEmpty(url)) { // 定义方法 方法(...)
            return RestResponse.validfail("该视频正在处理中"); // 返回 RestResponse.validfail("该视频正在处理中")
        } // 代码块结束
        return RestResponse.success(mediaFiles.getUrl()); // 返回 RestResponse.success(mediaFiles.getUrl())
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/api/main/com/xuecheng/MediaApplication.java

package com.xuecheng; // 声明类所在的包路径


import com.spring4all.swagger.EnableSwagger2Doc; // 导入 EnableSwagger2Doc 类
import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类

@EnableSwagger2Doc // 使用注解 @EnableSwagger2Doc
@SpringBootApplication // 使用注解 @SpringBootApplication
public class MediaApplication { // 定义 class MediaApplication
	public static void main(String[] args) { // 定义方法 main(...)
		SpringApplication.run(MediaApplication.class, args); // 执行语句
	} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/api/resources/bootstrap.yml

spring:
  application:
    name: media-api
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: minio-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
  profiles:
    active: dev

文件:xuecheng-plus-media/api/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="180" packages="">
    <properties>
        <property name="logdir">logs</property>
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${PATTERN}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="DEBUG" includeLocation="true">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

文件:xuecheng-plus-media/api_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-media</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-media-api</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-media-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
    </dependencies>
</project>

文件:xuecheng-plus-media/model/com/xuecheng/media/model/dto/QueryMediaParamsDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import io.swagger.annotations.ApiModelProperty; // 导入 ApiModelProperty 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 媒资文件查询请求模型类 // 保留原作者写的块注释
 * @date 2022/9/10 8:53 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class QueryMediaParamsDto { // 定义 class QueryMediaParamsDto

    @ApiModelProperty("媒资文件名称") // 使用注解 @ApiModelProperty("媒资文件名称")
    private String filename; // 执行语句
    @ApiModelProperty("媒资类型") // 使用注解 @ApiModelProperty("媒资类型")
    private String fileType; // 执行语句
    @ApiModelProperty("审核状态") // 使用注解 @ApiModelProperty("审核状态")
    private String auditStatus; // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/dto/UploadFileParamsDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 文件信息 // 保留原作者写的块注释
 * @date 2023/2/17 15:09 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class UploadFileParamsDto { // 定义 class UploadFileParamsDto

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句


    /** // 保留原作者写的块注释
     * 文件类型(文档,音频,视频) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileType; // 执行语句
    /** // 保留原作者写的块注释
     * 文件大小 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long fileSize; // 执行语句

    /** // 保留原作者写的块注释
     * 标签 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String tags; // 执行语句
    /** // 保留原作者写的块注释
     * 上传人 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String username; // 执行语句
    /** // 保留原作者写的块注释
     * 备注 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String remark; // 执行语句

} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/dto/UploadFileResultDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/17 15:06 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class UploadFileResultDto extends MediaFiles { // 定义 class UploadFileResultDto

} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/po/MediaFiles.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 * 媒资信息 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("media_files") // 使用注解 @TableName("media_files")
public class MediaFiles implements Serializable { // 定义 class MediaFiles

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 主键 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableId(value = "id", type = IdType.ASSIGN_ID) // 使用注解 @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 机构ID // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long companyId; // 执行语句

    /** // 保留原作者写的块注释
     * 机构名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String companyName; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 文件类型(文档,音频,视频) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileType; // 执行语句

    /** // 保留原作者写的块注释
     * 标签 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String tags; // 执行语句

    /** // 保留原作者写的块注释
     * 存储目录 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    /** // 保留原作者写的块注释
     * 存储路径 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filePath; // 执行语句


    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句


    /** // 保留原作者写的块注释
     * 上传人 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String username; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 修改时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT_UPDATE) // 使用注解 @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime changeDate; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 备注 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String remark; // 执行语句

    /** // 保留原作者写的块注释
     * 审核状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String auditStatus; // 执行语句

    /** // 保留原作者写的块注释
     * 审核意见 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String auditMind; // 执行语句

    /** // 保留原作者写的块注释
     * 文件大小 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long fileSize; // 执行语句

} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/po/MediaProcess.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("media_process") // 使用注解 @TableName("media_process")
public class MediaProcess implements Serializable { // 定义 class MediaProcess

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 存储源 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    private String filePath; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 完成时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime finishDate; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句

    /** // 保留原作者写的块注释
     * 失败原因 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String errormsg; // 执行语句

    /** // 保留原作者写的块注释
     * 失败次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private int failCount; // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/po/MediaProcessHistory.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("media_process_history") // 使用注解 @TableName("media_process_history")
public class MediaProcessHistory implements Serializable { // 定义 class MediaProcessHistory

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 存储源 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    private String filePath; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 完成时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime finishDate; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句
    /** // 保留原作者写的块注释
     * 失败原因 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String errormsg; // 执行语句

    /** // 保留原作者写的块注释
     * 失败次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private int failCount; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/po/MqMessage.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("mq_message") // 使用注解 @TableName("mq_message")
public class MqMessage implements Serializable { // 定义 class MqMessage

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 消息id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 消息类型代码 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String messageType; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey1; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey2; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey3; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqHost; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列端口 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer mqPort; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列虚拟主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqVirtualhost; // 执行语句

    /** // 保留原作者写的块注释
     * 队列名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqQueue; // 执行语句

    /** // 保留原作者写的块注释
     * 通知次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer informNum; // 执行语句

    /** // 保留原作者写的块注释
     * 处理状态,0:初始,1:成功,2:失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer state; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnfailureDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnsuccessDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败内容 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String returnfailureMsg; // 执行语句

    /** // 保留原作者写的块注释
     * 最近通知时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime informDate; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/model/com/xuecheng/media/model/po/MqMessageHistory.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("mq_message_history") // 使用注解 @TableName("mq_message_history")
public class MqMessageHistory implements Serializable { // 定义 class MqMessageHistory

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 消息id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 消息类型代码 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String messageType; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey1; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey2; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey3; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqHost; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列端口 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer mqPort; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列虚拟主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqVirtualhost; // 执行语句

    /** // 保留原作者写的块注释
     * 队列名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqQueue; // 执行语句

    /** // 保留原作者写的块注释
     * 通知次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer informNum; // 执行语句

    /** // 保留原作者写的块注释
     * 处理状态,0:初始,1:成功,2:失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer state; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnfailureDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnsuccessDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败内容 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String returnfailureMsg; // 执行语句

    /** // 保留原作者写的块注释
     * 最近通知时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime informDate; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/model_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-media</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-media-model</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-base</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

文件:xuecheng-plus-media/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-parent</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        <relativePath>../xuecheng-plus-parent</relativePath> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-media</artifactId> <!-- SQL 语句片段 -->
    <name>xuecheng-plus-media</name> <!-- SQL 语句片段 -->
    <description>xuecheng-plus-media</description> <!-- SQL 语句片段 -->
    <packaging>pom</packaging> <!-- SQL 语句片段 -->

    <modules> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-media-api</module> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-media-service</module> <!-- SQL 语句片段 -->
        <module>xuecheng-plus-media-model</module> <!-- SQL 语句片段 -->
    </modules> <!-- SQL 语句片段 -->
</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/root_pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- 媒资模块聚合 POM -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-parent</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../xuecheng-plus-parent</relativePath>
    </parent>
    <packaging>pom</packaging>
    <artifactId>xuecheng-plus-media</artifactId>
    <modules>
        <module>xuecheng-plus-media-api</module>
        <module>xuecheng-plus-media-model</module>
        <module>xuecheng-plus-media-service</module>
    </modules>
</project>

文件:xuecheng-plus-media/service/main/com/xuecheng/media/config/MinioConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import io.minio.MinioClient; // 导入 MinioClient 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/17 15:00 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class MinioConfig { // 定义 class MinioConfig
 @Value("${minio.endpoint}") // 使用注解 @Value("${minio.endpoint}")
 private String endpoint; // 执行语句
 @Value("${minio.accessKey}") // 使用注解 @Value("${minio.accessKey}")
 private String accessKey; // 执行语句
 @Value("${minio.secretKey}") // 使用注解 @Value("${minio.secretKey}")
 private String secretKey; // 执行语句

 @Bean // 使用注解 @Bean
 public MinioClient minioClient() { // 定义方法 minioClient(...)

  MinioClient minioClient = // 代码逻辑
          MinioClient.builder() // 代码逻辑
                  .endpoint(endpoint) // 代码逻辑
                  .credentials(accessKey, secretKey) // 代码逻辑
                  .build(); // 执行语句
  return minioClient; // 返回 minioClient
 } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/config/MybatisPlusConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.DbType; // 导入 DbType 类
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; // 导入 MybatisPlusInterceptor 类
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; // 导入 PaginationInnerInterceptor 类
import org.mybatis.spring.annotation.MapperScan; // 导入 MapperScan 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * <P> // 保留原作者写的块注释
 * 		Mybatis-Plus 配置 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@MapperScan("com.xuecheng.media.mapper") // 使用注解 @MapperScan("com.xuecheng.media.mapper")
public class MybatisPlusConfig { // 定义 class MybatisPlusConfig
	/** // 保留原作者写的块注释
	 * 新的分页插件 // 保留原作者写的块注释
	 * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false // 保留原作者写的块注释
	 * 避免缓存出现问题(该属性会在旧插件移除后一同移除) // 保留原作者写的块注释
	 */ // 保留原作者写的块注释
	@Bean // 使用注解 @Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() { // 定义方法 mybatisPlusInterceptor(...)
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建 MybatisPlusInterceptor 对象并赋值给 interceptor
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 执行语句
		return interceptor; // 返回 interceptor
	} // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/config/XxlJobConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; // 导入 XxlJobSpringExecutor 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * xxl-job config // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author xuxueli 2017-04-28 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class XxlJobConfig { // 定义 class XxlJobConfig
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); // 把 LoggerFactory.getLogger(XxlJobConfig.class) 赋值给 logger

    @Value("${xxl.job.admin.addresses}") // 使用注解 @Value("${xxl.job.admin.addresses}")
    private String adminAddresses; // 执行语句

    @Value("${xxl.job.accessToken}") // 使用注解 @Value("${xxl.job.accessToken}")
    private String accessToken; // 执行语句

    @Value("${xxl.job.executor.appname}") // 使用注解 @Value("${xxl.job.executor.appname}")
    private String appname; // 执行语句

    @Value("${xxl.job.executor.address}") // 使用注解 @Value("${xxl.job.executor.address}")
    private String address; // 执行语句

    @Value("${xxl.job.executor.ip}") // 使用注解 @Value("${xxl.job.executor.ip}")
    private String ip; // 执行语句

    @Value("${xxl.job.executor.port}") // 使用注解 @Value("${xxl.job.executor.port}")
    private int port; // 执行语句

    @Value("${xxl.job.executor.logpath}") // 使用注解 @Value("${xxl.job.executor.logpath}")
    private String logPath; // 执行语句

    @Value("${xxl.job.executor.logretentiondays}") // 使用注解 @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays; // 执行语句


    @Bean // 使用注解 @Bean
    public XxlJobSpringExecutor xxlJobExecutor() { // 定义方法 xxlJobExecutor(...)
        logger.info(">>>>>>>>>>> xxl-job config init."); // 执行语句
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); // 创建 XxlJobSpringExecutor 对象并赋值给 xxlJobSpringExecutor
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses); // 执行语句
        xxlJobSpringExecutor.setAppname(appname); // 执行语句
        xxlJobSpringExecutor.setAddress(address); // 执行语句
        xxlJobSpringExecutor.setIp(ip); // 执行语句
        xxlJobSpringExecutor.setPort(port); // 执行语句
        xxlJobSpringExecutor.setAccessToken(accessToken); // 执行语句
        xxlJobSpringExecutor.setLogPath(logPath); // 执行语句
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); // 执行语句

        return xxlJobSpringExecutor; // 返回 xxlJobSpringExecutor
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP; // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      1、引入依赖: // 保留原作者写的块注释
     *          <dependency> // 保留原作者写的块注释
     *             <groupId>org.springframework.cloud</groupId> // 保留原作者写的块注释
     *             <artifactId>spring-cloud-commons</artifactId> // 保留原作者写的块注释
     *             <version>${version}</version> // 保留原作者写的块注释
     *         </dependency> // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      2、配置文件,或者容器启动变量 // 保留原作者写的块注释
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.' // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      3、获取IP // 保留原作者写的块注释
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); // 保留原作者写的块注释
     */ // 保留原作者写的块注释


} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaFilesMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 * 媒资信息 Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFilesMapper extends BaseMapper<MediaFiles> { // 定义 interface MediaFilesMapper

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaFilesMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaFilesMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaFiles"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="company_id" property="companyId" /> <!-- 字段与属性的映射规则 -->
        <result column="company_name" property="companyName" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="file_type" property="fileType" /> <!-- 字段与属性的映射规则 -->
        <result column="tags" property="tags" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
        <result column="timelength" property="timelength" /> <!-- 字段与属性的映射规则 -->
        <result column="username" property="username" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="change_date" property="changeDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="remark" property="remark" /> <!-- 字段与属性的映射规则 -->
        <result column="audit_status" property="auditStatus" /> <!-- 字段与属性的映射规则 -->
        <result column="audit_mind" property="auditMind" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, company_id, company_name, filename, file_type, tags, bucket, file_id, url, timelength, username, create_date, change_date, status, remark, audit_status, audit_mind <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaProcessHistoryMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaProcessHistory; // 导入 MediaProcessHistory 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaProcessHistoryMapper extends BaseMapper<MediaProcessHistory> { // 定义 interface MediaProcessHistoryMapper

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaProcessHistoryMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaProcessHistoryMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaProcessHistory"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="finish_date" property="finishDate" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, file_id, filename, bucket, status, create_date, finish_date, url <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaProcessMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import org.apache.ibatis.annotations.Param; // 导入 Param 类
import org.apache.ibatis.annotations.Select; // 导入 Select 类
import org.apache.ibatis.annotations.Update; // 导入 Update 类

import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaProcessMapper extends BaseMapper<MediaProcess> { // 定义 interface MediaProcessMapper

    @Select("select * from media_process t where  t.id % #{shardTotal} = #{shardIndex} and (t.status=1 or t.status=3) and t.fail_count<3 limit #{count}") // 使用注解 @Select("select * from media_process t where  t.id % #{shardTotal} = #{shardIndex} and (t.status=1 or t.status=3) and t.fail_count<3 limit #{count}")
    List<MediaProcess>  selectListByShardIndex(@Param("shardTotal") int shardTotal, @Param("shardIndex") int shardIndex, @Param("count") int count); // 执行语句

    /** // 保留原作者写的块注释
     * 开启一个任务 // 保留原作者写的块注释
     * @param id 任务id // 保留原作者写的块注释
     * @return 更新记录数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Update("update media_process m set m.status='4' where (m.status='1' or m.status='3') and m.fail_count<3 and m.id=#{id}") // 使用注解 @Update("update media_process m set m.status='4' where (m.status='1' or m.status='3') and m.fail_count<3 and m.id=#{id}")
    int startTask(@Param("id") long id); // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MediaProcessMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaProcessMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaProcess"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="finish_date" property="finishDate" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, file_id, filename, bucket, status, create_date, finish_date, url <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MqMessageHistoryMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MqMessageHistory; // 导入 MqMessageHistory 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MqMessageHistoryMapper extends BaseMapper<MqMessageHistory> { // 定义 interface MqMessageHistoryMapper

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MqMessageHistoryMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MqMessageHistoryMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MqMessageHistory"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="message_type" property="messageType" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key1" property="businessKey1" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key2" property="businessKey2" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key3" property="businessKey3" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_host" property="mqHost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_port" property="mqPort" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_virtualhost" property="mqVirtualhost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_queue" property="mqQueue" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_num" property="informNum" /> <!-- 字段与属性的映射规则 -->
        <result column="state" property="state" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_date" property="returnfailureDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnsuccess_date" property="returnsuccessDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_msg" property="returnfailureMsg" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_date" property="informDate" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, message_type, business_key1, business_key2, business_key3, mq_host, mq_port, mq_virtualhost, mq_queue, inform_num, state, returnfailure_date, returnsuccess_date, returnfailure_msg, inform_date <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MqMessageMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MqMessage; // 导入 MqMessage 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MqMessageMapper extends BaseMapper<MqMessage> { // 定义 interface MqMessageMapper

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/mapper/MqMessageMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MqMessageMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MqMessage"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="message_type" property="messageType" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key1" property="businessKey1" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key2" property="businessKey2" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key3" property="businessKey3" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_host" property="mqHost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_port" property="mqPort" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_virtualhost" property="mqVirtualhost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_queue" property="mqQueue" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_num" property="informNum" /> <!-- 字段与属性的映射规则 -->
        <result column="state" property="state" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_date" property="returnfailureDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnsuccess_date" property="returnsuccessDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_msg" property="returnfailureMsg" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_date" property="informDate" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, message_type, business_key1, business_key2, business_key3, mq_host, mq_port, mq_virtualhost, mq_queue, inform_num, state, returnfailure_date, returnsuccess_date, returnfailure_msg, inform_date <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/impl/MediaFileProcessServiceImpl.java

package com.xuecheng.media.service.impl; // 声明类所在的包路径

import com.xuecheng.media.mapper.MediaFilesMapper; // 导入 MediaFilesMapper 类
import com.xuecheng.media.mapper.MediaProcessHistoryMapper; // 导入 MediaProcessHistoryMapper 类
import com.xuecheng.media.mapper.MediaProcessMapper; // 导入 MediaProcessMapper 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.model.po.MediaProcessHistory; // 导入 MediaProcessHistory 类
import com.xuecheng.media.service.MediaFileProcessService; // 导入 MediaFileProcessService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Service; // 导入 Service 类

import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description MediaFileProcess接口实现 // 保留原作者写的块注释
 * @date 2023/2/19 10:44 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class MediaFileProcessServiceImpl implements MediaFileProcessService { // 定义 class MediaFileProcessServiceImpl
    @Autowired // 使用注解 @Autowired
    MediaProcessMapper mediaProcessMapper; // 执行语句
    @Autowired // 使用注解 @Autowired
    MediaProcessHistoryMapper mediaProcessHistoryMapper; // 执行语句
    @Autowired // 使用注解 @Autowired
    MediaFilesMapper mediaFilesMapper; // 执行语句

    @Override // 使用注解 @Override
    public List<MediaProcess> getMediaProcessList(int shardIndex, int shardTotal, int count) { // 定义方法 getMediaProcessList(...)
        List<MediaProcess> mediaProcesses = mediaProcessMapper.selectListByShardIndex(shardTotal, shardIndex, count); // 把 mediaProcessMapper.selectListByShardIndex(shardTotal, shardIndex, count) 赋值给 mediaProcesses
        return mediaProcesses; // 返回 mediaProcesses
    } // 代码块结束

    //实现如下 // 保留原作者写的行内注释
    public boolean startTask(long id) { // 定义方法 startTask(...)
        int result = mediaProcessMapper.startTask(id); // 把 mediaProcessMapper.startTask(id) 赋值给 result
        return result<=0?false:true; // 返回 result<=0?false:true
    } // 代码块结束

    @Override // 使用注解 @Override
    public void saveProcessFinishStatus(Long taskId, String status, String fileId, String url, String errorMsg) { // 定义方法 saveProcessFinishStatus(...)

        //要更新的任务 // 保留原作者写的行内注释
        MediaProcess mediaProcess = mediaProcessMapper.selectById(taskId); // 把 mediaProcessMapper.selectById(taskId) 赋值给 mediaProcess
        if(mediaProcess == null){ // 定义方法 方法(...)
            return ; // 返回 
        } // 代码块结束
        //如果任务执行失败 // 保留原作者写的行内注释
        if(status.equals("3")){ // 定义方法 方法(...)
            //更新MediaProcess表的状态 // 保留原作者写的行内注释
            mediaProcess.setStatus("3"); // 执行语句
            mediaProcess.setFailCount(mediaProcess.getFailCount()+1);//失败次数加1 // 执行语句
            mediaProcess.setErrormsg(errorMsg); // 执行语句
            mediaProcessMapper.updateById(mediaProcess); // 执行语句
            //更高效的更新方式 // 保留原作者写的行内注释
//            mediaProcessMapper.update() // 保留原作者写的行内注释
            //todo:将上边的更新方式更改为效的更新方式 // 保留原作者写的行内注释
            return; // 直接返回不带结果

        } // 代码块结束


        //======如果任务执行成功====== // 保留原作者写的行内注释
        //文件表记录 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileId); // 把 mediaFilesMapper.selectById(fileId) 赋值给 mediaFiles
        //更新media_file表中的url // 保留原作者写的行内注释
        mediaFiles.setUrl(url); // 执行语句
        mediaFilesMapper.updateById(mediaFiles); // 执行语句

        //更新MediaProcess表的状态 // 保留原作者写的行内注释
        mediaProcess.setStatus("2"); // 执行语句
        mediaProcess.setFinishDate(LocalDateTime.now()); // 执行语句
        mediaProcess.setUrl(url); // 执行语句
        mediaProcessMapper.updateById(mediaProcess); // 执行语句

        //将MediaProcess表记录插入到MediaProcessHistory表 // 保留原作者写的行内注释
        MediaProcessHistory mediaProcessHistory = new MediaProcessHistory(); // 创建 MediaProcessHistory 对象并赋值给 mediaProcessHistory
        BeanUtils.copyProperties(mediaProcess,mediaProcessHistory); // 执行语句
        mediaProcessHistoryMapper.insert(mediaProcessHistory); // 执行语句

        //从MediaProcess删除当前任务 // 保留原作者写的行内注释
        mediaProcessMapper.deleteById(taskId); // 执行语句


    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/impl/MediaFileServiceImpl.java

package com.xuecheng.media.service.impl; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 导入 LambdaQueryWrapper 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 Page 类
import com.j256.simplemagic.ContentInfo; // 导入 ContentInfo 类
import com.j256.simplemagic.ContentInfoUtil; // 导入 ContentInfoUtil 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.mapper.MediaFilesMapper; // 导入 MediaFilesMapper 类
import com.xuecheng.media.mapper.MediaProcessMapper; // 导入 MediaProcessMapper 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.minio.*; // 导入 * 类
import io.minio.errors.*; // 导入 * 类
import io.minio.messages.DeleteError; // 导入 DeleteError 类
import io.minio.messages.DeleteObject; // 导入 DeleteObject 类
import io.minio.messages.DeletedObject; // 导入 DeletedObject 类
import io.minio.messages.Item; // 导入 Item 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.apache.commons.codec.digest.DigestUtils; // 导入 DigestUtils 类
import org.apache.commons.io.IOUtils; // 导入 IOUtils 类
import org.apache.commons.lang3.StringUtils; // 导入 StringUtils 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.http.MediaType; // 导入 MediaType 类
import org.springframework.stereotype.Service; // 导入 Service 类
import org.springframework.transaction.annotation.Transactional; // 导入 Transactional 类

import java.io.*; // 导入 * 类
import java.security.InvalidKeyException; // 导入 InvalidKeyException 类
import java.security.NoSuchAlgorithmException; // 导入 NoSuchAlgorithmException 类
import java.text.SimpleDateFormat; // 导入 SimpleDateFormat 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.Date; // 导入 Date 类
import java.util.List; // 导入 List 类
import java.util.stream.Collectors; // 导入 Collectors 类
import java.util.stream.Stream; // 导入 Stream 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2022/9/10 8:58 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class MediaFileServiceImpl implements MediaFileService { // 定义 class MediaFileServiceImpl

    @Autowired // 使用注解 @Autowired
    MediaFilesMapper mediaFilesMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    MinioClient minioClient; // 执行语句

    // // 保留原作者写的行内注释
    @Autowired // 使用注解 @Autowired
    MediaFileService currentProxy; // 执行语句

    @Autowired // 使用注解 @Autowired
    MediaProcessMapper mediaProcessMapper; // 执行语句

    //存储普通文件 // 保留原作者写的行内注释
    @Value("${minio.bucket.files}") // 使用注解 @Value("${minio.bucket.files}")
    private String bucket_mediafiles; // 执行语句

    //存储视频 // 保留原作者写的行内注释
    @Value("${minio.bucket.videofiles}") // 使用注解 @Value("${minio.bucket.videofiles}")
    private String bucket_video; // 执行语句

    @Override // 使用注解 @Override
    public MediaFiles getFileById(String mediaId) { // 定义方法 getFileById(...)
        MediaFiles mediaFiles = mediaFilesMapper.selectById(mediaId); // 把 mediaFilesMapper.selectById(mediaId) 赋值给 mediaFiles
        return mediaFiles; // 返回 mediaFiles
    } // 代码块结束

    @Override // 使用注解 @Override
    public PageResult<MediaFiles> queryMediaFiels(Long companyId, PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto) { // 定义方法 queryMediaFiels(...)

        //构建查询条件对象 // 保留原作者写的行内注释
        LambdaQueryWrapper<MediaFiles> queryWrapper = new LambdaQueryWrapper<>(); // 创建 LambdaQueryWrapper<> 对象并赋值给 queryWrapper

        //分页对象 // 保留原作者写的行内注释
        Page<MediaFiles> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize()); // 创建 Page<> 对象并赋值给 page
        // 查询数据内容获得结果 // 保留原作者写的行内注释
        Page<MediaFiles> pageResult = mediaFilesMapper.selectPage(page, queryWrapper); // 把 mediaFilesMapper.selectPage(page, queryWrapper) 赋值给 pageResult
        // 获取数据列表 // 保留原作者写的行内注释
        // getRecords系统只带 // 保留原作者写的行内注释
        List<MediaFiles> list = pageResult.getRecords(); // 把 pageResult.getRecords() 的返回值赋给 list
        // 获取数据总数 // 保留原作者写的行内注释
        // getTotal系统自带 // 保留原作者写的行内注释
        long total = pageResult.getTotal(); // 把 pageResult.getTotal() 的返回值赋给 total
        // 构建结果集 // 保留原作者写的行内注释
        PageResult<MediaFiles> mediaListResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize()); // 创建 PageResult<> 对象并赋值给 mediaListResult
        return mediaListResult; // 返回 mediaListResult

    } // 代码块结束

    //根据文件扩展名(例如 .mp4)获取mimeType(该文件的MIME) // 保留原作者写的行内注释
    // MIME每个文件或数据块都可以用一个MIME类型字符串来描述自己的格式 // 保留原作者写的行内注释
    private String getMimeType(String extension){ // 定义方法 getMimeType(...)
        // 如果拿不到文件扩展名,于是把它看成空串,避免后续工具遇到null报错 // 保留原作者写的行内注释
        if(extension == null){ // 定义方法 方法(...)
            extension = ""; // 把 "" 赋值给 extension
        } // 代码块结束
        //根据扩展名取出mimeType // 保留原作者写的行内注释
        // ContentInfo用来描述文件识别的效果 // 保留原作者写的行内注释
        //findExtensionMatch根据文件扩展名返回,里面保护焊该类型的MIME类型,匹配度,文件描述等信息 // 保留原作者写的行内注释
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension); // 把 ContentInfoUtil.findExtensionMatch(extension) 赋值给 extensionMatch
        // MediaType是Spring框架提供的一个类型 // 保留原作者写的行内注释
        // 防止没有拿到文件扩展名,当无法判断文件的具体类型时,用这个告诉客户端,这是原始字节流,你按下载即可 // 保留原作者写的行内注释
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE; // 把 MediaType.APPLICATION_OCTET_STREAM_VALUE 赋值给 mimeType
        //通用mimeType,字节流 // 保留原作者写的行内注释
        if(extensionMatch!=null){ // 定义方法 方法(...)
            // getMimeType负责吧文件扩展名转换成标准MIME类型字符串 // 保留原作者写的行内注释
            // mimeType这个文件是什么类型 // 保留原作者写的行内注释
            mimeType = extensionMatch.getMimeType(); // 把 extensionMatch.getMimeType() 的返回值赋给 mimeType
        } // 代码块结束
        return mimeType; // 返回 mimeType

    } // 代码块结束

    /** // 保留原作者写的块注释
     * 将文件上传到minio // 保留原作者写的块注释
     * @param localFilePath 文件本地路径 // 保留原作者写的块注释
     * @param mimeType 媒体类型 // 保留原作者写的块注释
     * @param bucket 桶 // 保留原作者写的块注释
     * @param objectName 对象名 // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName){ // 定义方法 addMediaFilesToMinIO(...)
        try { // 尝试执行可能抛出异常的代码
            // Upload // 保留原作者写的行内注释
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder() // 代码逻辑
                    .bucket(bucket)//桶 // 代码逻辑
                    .filename(localFilePath) //指定本地文件路径 // 代码逻辑
                    .object(objectName)//对象名 放在子目录下 // 代码逻辑
                    .contentType(mimeType)//设置媒体文件类型 // 代码逻辑
                    .build(); // 执行语句
            //上传文件 // 保留原作者写的行内注释
            minioClient.uploadObject(uploadObjectArgs); // 执行语句
            log.debug("上传文件到minio成功,bucket:{},objectName:{},错误信息:{}",bucket,objectName); // 执行语句
            return true; // 返回 true
        } catch (Exception e) { // 定义方法 catch(...)
           e.printStackTrace(); // 执行语句
           log.error("上传文件出错,bucket:{},objectName:{},错误信息:{}",bucket,objectName,e.getMessage()); // 执行语句
        } // 代码块结束
        return false; // 返回 false
    } // 代码块结束

    //获取文件默认存储目录路径 年/月/日 // 保留原作者写的行内注释
    private String getDefaultFolderPath() { // 定义方法 getDefaultFolderPath(...)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 创建 SimpleDateFormat 对象并赋值给 sdf
        String folder = sdf.format(new Date()).replace("-", "/")+"/"; // 把 sdf.format(new Date()).replace("-", "/")+"/" 赋值给 folder
        return folder; // 返回 folder
    } // 代码块结束
    //获取文件的md5 // 保留原作者写的行内注释
    private String getFileMd5(File file) { // 定义方法 getFileMd5(...)
        try (FileInputStream fileInputStream = new FileInputStream(file)) { // 定义方法 FileInputStream(...)
            String fileMd5 = DigestUtils.md5Hex(fileInputStream); // 把 DigestUtils.md5Hex(fileInputStream) 赋值给 fileMd5
            return fileMd5; // 返回 fileMd5
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
            return null; // 返回 null
        } // 代码块结束
    } // 代码块结束

    @Override // 使用注解 @Override
    public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath,String objectName) { // 定义方法 uploadFile(...)

        //文件名 // 保留原作者写的行内注释
        String filename = uploadFileParamsDto.getFilename(); // 把 uploadFileParamsDto.getFilename() 的返回值赋给 filename
        //先得到扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension

        //得到mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(extension); // 把 getMimeType(extension) 赋值给 mimeType

        //子目录 // 保留原作者写的行内注释
        String defaultFolderPath = getDefaultFolderPath(); // 把 getDefaultFolderPath() 的返回值赋给 defaultFolderPath
        //文件的md5值 // 保留原作者写的行内注释
        String fileMd5 = getFileMd5(new File(localFilePath)); // 把 getFileMd5(new File(localFilePath)) 赋值给 fileMd5
        if(StringUtils.isEmpty(objectName)){ // 定义方法 方法(...)
            //使用默认年月日去存储 // 保留原作者写的行内注释
            objectName = defaultFolderPath+fileMd5+extension; // 把 defaultFolderPath+fileMd5+extension 赋值给 objectName
        } // 代码块结束
        //上传文件到minio // 保留原作者写的行内注释
        boolean result = addMediaFilesToMinIO(localFilePath, mimeType, bucket_mediafiles, objectName); // 把 addMediaFilesToMinIO(localFilePath, mimeType, bucket_mediafiles, objectName) 赋值给 result
        if(!result){ // 定义方法 方法(...)
            XueChengPlusException.cast("上传文件失败"); // 执行语句
        } // 代码块结束
        //入库文件信息 // 保留原作者写的行内注释
        MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName); // 把 currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName) 赋值给 mediaFiles
        if(mediaFiles==null){ // 定义方法 方法(...)
            XueChengPlusException.cast("文件上传后保存信息失败"); // 执行语句
        } // 代码块结束
        //准备返回的对象 // 保留原作者写的行内注释
        UploadFileResultDto uploadFileResultDto = new UploadFileResultDto(); // 创建 UploadFileResultDto 对象并赋值给 uploadFileResultDto
        BeanUtils.copyProperties(mediaFiles,uploadFileResultDto); // 执行语句

        return uploadFileResultDto; // 返回 uploadFileResultDto
    } // 代码块结束


    /** // 保留原作者写的块注释
     * @description 将文件信息添加到文件表 // 保留原作者写的块注释
     * @param companyId  机构id // 保留原作者写的块注释
     * @param fileMd5  文件md5值 // 保留原作者写的块注释
     * @param uploadFileParamsDto  上传文件的信息 // 保留原作者写的块注释
     * @param bucket  桶 // 保留原作者写的块注释
     * @param objectName 对象名称 // 保留原作者写的块注释
     * @return com.xuecheng.media.model.po.MediaFiles // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/12 21:22 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Transactional // 使用注解 @Transactional
    public MediaFiles addMediaFilesToDb(Long companyId,String fileMd5,UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName){ // 定义方法 addMediaFilesToDb(...)
        //将文件信息保存到数据库 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5); // 把 mediaFilesMapper.selectById(fileMd5) 赋值给 mediaFiles
        if(mediaFiles == null){ // 定义方法 方法(...)
            mediaFiles = new MediaFiles(); // 创建 MediaFiles 对象并赋值给 mediaFiles
            BeanUtils.copyProperties(uploadFileParamsDto,mediaFiles); // 执行语句
            //文件id // 保留原作者写的行内注释
            mediaFiles.setId(fileMd5); // 执行语句
            //机构id // 保留原作者写的行内注释
            mediaFiles.setCompanyId(companyId); // 执行语句
            //桶 // 保留原作者写的行内注释
            mediaFiles.setBucket(bucket); // 执行语句
            //file_path // 保留原作者写的行内注释
            mediaFiles.setFilePath(objectName); // 执行语句
            //file_id // 保留原作者写的行内注释
            mediaFiles.setFileId(fileMd5); // 执行语句
            //url // 保留原作者写的行内注释
            mediaFiles.setUrl("/"+bucket+"/"+objectName); // 执行语句
            //上传时间 // 保留原作者写的行内注释
            mediaFiles.setCreateDate(LocalDateTime.now()); // 执行语句
            //状态 // 保留原作者写的行内注释
            mediaFiles.setStatus("1"); // 执行语句
            //审核状态 // 保留原作者写的行内注释
            mediaFiles.setAuditStatus("002003"); // 执行语句
            //插入数据库 // 保留原作者写的行内注释
            int insert = mediaFilesMapper.insert(mediaFiles); // 把 mediaFilesMapper.insert(mediaFiles) 赋值给 insert
            if(insert<=0){ // 定义方法 方法(...)
                log.debug("向数据库保存文件失败,bucket:{},objectName:{}",bucket,objectName); // 执行语句
                return null; // 返回 null
            } // 代码块结束
            //记录待处理任务 // 保留原作者写的行内注释
            addWaitingTask(mediaFiles); // 执行语句

            return mediaFiles; // 返回 mediaFiles

        } // 代码块结束
        return mediaFiles; // 返回 mediaFiles

    } // 代码块结束


    /** // 保留原作者写的块注释
     * 添加待处理任务 // 保留原作者写的块注释
     * @param mediaFiles 媒资文件信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private void addWaitingTask(MediaFiles mediaFiles){ // 定义方法 addWaitingTask(...)

        //文件名称 // 保留原作者写的行内注释
        String filename = mediaFiles.getFilename(); // 把 mediaFiles.getFilename() 的返回值赋给 filename
        //文件扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension
        //获取文件的 mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(extension); // 把 getMimeType(extension) 赋值给 mimeType
        if(mimeType.equals("video/x-msvideo")){//如果是avi视频写入待处理任务 // 定义方法 方法(...)
            MediaProcess mediaProcess = new MediaProcess(); // 创建 MediaProcess 对象并赋值给 mediaProcess
            BeanUtils.copyProperties(mediaFiles,mediaProcess); // 执行语句
            //状态是未处理 // 保留原作者写的行内注释
            mediaProcess.setStatus("1"); // 执行语句
            mediaProcess.setCreateDate(LocalDateTime.now()); // 执行语句
            mediaProcess.setFailCount(0);//失败次数默认0 // 执行语句
            mediaProcess.setUrl(null); // 执行语句
            mediaProcessMapper.insert(mediaProcess); // 执行语句

        } // 代码块结束

    } // 代码块结束


    @Override // 使用注解 @Override
    public RestResponse<Boolean> checkFile(String fileMd5) { // 定义方法 checkFile(...)
        //先查询数据库 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5); // 把 mediaFilesMapper.selectById(fileMd5) 赋值给 mediaFiles
        if(mediaFiles!=null){ // 定义方法 方法(...)
            //桶 // 保留原作者写的行内注释
            String bucket = mediaFiles.getBucket(); // 把 mediaFiles.getBucket() 的返回值赋给 bucket
            //objectname // 保留原作者写的行内注释
            String filePath = mediaFiles.getFilePath(); // 把 mediaFiles.getFilePath() 的返回值赋给 filePath
            //如果数据库存在再查询 minio // 保留原作者写的行内注释
            GetObjectArgs getObjectArgs = GetObjectArgs.builder() // 代码逻辑
                    .bucket(bucket) // 代码逻辑
                    .object(filePath) // 代码逻辑
                    .build(); // 执行语句
            //查询远程服务获取到一个流对象 // 保留原作者写的行内注释
            try { // 尝试执行可能抛出异常的代码
                FilterInputStream inputStream = minioClient.getObject(getObjectArgs); // 把 minioClient.getObject(getObjectArgs) 赋值给 inputStream
                if(inputStream!=null){ // 定义方法 方法(...)
                    //文件已存在 // 保留原作者写的行内注释
                    return RestResponse.success(true); // 返回 RestResponse.success(true)
                } // 代码块结束
            } catch (Exception e) { // 定义方法 catch(...)
                e.printStackTrace(); // 执行语句
            } // 代码块结束

        } // 代码块结束

        //文件不存在 // 保留原作者写的行内注释
        return RestResponse.success(false); // 返回 RestResponse.success(false)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex) { // 定义方法 checkChunk(...)

        //根据md5得到分块文件所在目录的路径 // 保留原作者写的行内注释
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5); // 把 getChunkFileFolderPath(fileMd5) 赋值给 chunkFileFolderPath

        //如果数据库存在再查询 minio // 保留原作者写的行内注释
        GetObjectArgs getObjectArgs = GetObjectArgs.builder() // 代码逻辑
                .bucket(bucket_video) // 代码逻辑
                .object(chunkFileFolderPath+chunkIndex) // 代码逻辑
                .build(); // 执行语句
        //查询远程服务获取到一个流对象 // 保留原作者写的行内注释
        try { // 尝试执行可能抛出异常的代码
            FilterInputStream inputStream = minioClient.getObject(getObjectArgs); // 把 minioClient.getObject(getObjectArgs) 赋值给 inputStream
            if(inputStream!=null){ // 定义方法 方法(...)
                //文件已存在 // 保留原作者写的行内注释
                return RestResponse.success(true); // 返回 RestResponse.success(true)
            } // 代码块结束
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
        } // 代码块结束

        //文件不存在 // 保留原作者写的行内注释
        return RestResponse.success(false); // 返回 RestResponse.success(false)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse uploadChunk(String fileMd5, int chunk, String localChunkFilePath) { // 定义方法 uploadChunk(...)
        //分块文件的路径 // 保留原作者写的行内注释
        String chunkFilePath = getChunkFileFolderPath(fileMd5) + chunk; // 把 getChunkFileFolderPath(fileMd5) + chunk 赋值给 chunkFilePath
        //获取mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(null); // 把 getMimeType(null) 赋值给 mimeType
        //将分块文件上传到minio // 保留原作者写的行内注释
        boolean b = addMediaFilesToMinIO(localChunkFilePath, mimeType, bucket_video, chunkFilePath); // 把 addMediaFilesToMinIO(localChunkFilePath, mimeType, bucket_video, chunkFilePath) 赋值给 b
        if(!b){ // 定义方法 方法(...)
            return RestResponse.validfail(false,"上传分块文件失败"); // 返回 RestResponse.validfail(false,"上传分块文件失败")
        } // 代码块结束
        //上传成功 // 保留原作者写的行内注释
        return RestResponse.success(true); // 返回 RestResponse.success(true)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse mergechunks(Long companyId, String fileMd5, int chunkTotal, UploadFileParamsDto uploadFileParamsDto) { // 定义方法 mergechunks(...)
        //分块文件所在目录 // 保留原作者写的行内注释
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5); // 把 getChunkFileFolderPath(fileMd5) 赋值给 chunkFileFolderPath
        //找到所有的分块文件 // 保留原作者写的行内注释
        List<ComposeSource> sources = Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> ComposeSource.builder().bucket(bucket_video).object(chunkFileFolderPath + i).build()).collect(Collectors.toList()); // 把 Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> ComposeSource.builder().bucket(bucket_video).object(chunkFileFolderPath + i).build()).collect(Collectors.toList()) 赋值给 sources
        //源文件名称 // 保留原作者写的行内注释
        String filename = uploadFileParamsDto.getFilename(); // 把 uploadFileParamsDto.getFilename() 的返回值赋给 filename
        //扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension
        //合并后文件的objectname // 保留原作者写的行内注释
        String objectName = getFilePathByMd5(fileMd5, extension); // 把 getFilePathByMd5(fileMd5, extension) 赋值给 objectName
        //指定合并后的objectName等信息 // 保留原作者写的行内注释
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder() // 代码逻辑
                .bucket(bucket_video) // 代码逻辑
                .object(objectName)//合并后的文件的objectname // 代码逻辑
                .sources(sources)//指定源文件 // 代码逻辑
                .build(); // 执行语句
        //===========合并文件============ // 保留原作者写的行内注释
        //报错size 1048576 must be greater than 5242880,minio默认的分块文件大小为5M // 保留原作者写的行内注释
        try { // 尝试执行可能抛出异常的代码
            minioClient.composeObject(composeObjectArgs); // 执行语句
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
            log.error("合并文件出错,bucket:{},objectName:{},错误信息:{}",bucket_video,objectName,e.getMessage()); // 执行语句
            return RestResponse.validfail(false,"合并文件异常"); // 返回 RestResponse.validfail(false,"合并文件异常")
        } // 代码块结束

        //===========校验合并后的和源文件是否一致,视频上传才成功=========== // 保留原作者写的行内注释
        //先下载合并后的文件 // 保留原作者写的行内注释
        File file = downloadFileFromMinIO(bucket_video, objectName); // 把 downloadFileFromMinIO(bucket_video, objectName) 赋值给 file
        try(FileInputStream fileInputStream = new FileInputStream(file)){ // 定义方法 FileInputStream(...)
            //计算合并后文件的md5 // 保留原作者写的行内注释
            String mergeFile_md5 = DigestUtils.md5Hex(fileInputStream); // 把 DigestUtils.md5Hex(fileInputStream) 赋值给 mergeFile_md5
            //比较原始md5和合并后文件的md5 // 保留原作者写的行内注释
            if(!fileMd5.equals(mergeFile_md5)){ // 定义方法 方法(...)
                log.error("校验合并文件md5值不一致,原始文件:{},合并文件:{}",fileMd5,mergeFile_md5); // 执行语句
                return RestResponse.validfail(false,"文件校验失败"); // 返回 RestResponse.validfail(false,"文件校验失败")
            } // 代码块结束
            //文件大小 // 保留原作者写的行内注释
            uploadFileParamsDto.setFileSize(file.length()); // 执行语句
        }catch (Exception e) { // 定义方法 方法(...)
            return RestResponse.validfail(false,"文件校验失败"); // 返回 RestResponse.validfail(false,"文件校验失败")
        } // 代码块结束

        //==============将文件信息入库============ // 保留原作者写的行内注释
        MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_video, objectName); // 把 currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_video, objectName) 赋值给 mediaFiles
        if(mediaFiles == null){ // 定义方法 方法(...)
            return RestResponse.validfail(false,"文件入库失败"); // 返回 RestResponse.validfail(false,"文件入库失败")
        } // 代码块结束
        //==========清理分块文件========= // 保留原作者写的行内注释
        clearChunkFiles(chunkFileFolderPath,chunkTotal); // 执行语句


        return RestResponse.success(true); // 返回 RestResponse.success(true)
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 清除分块文件 // 保留原作者写的块注释
     * @param chunkFileFolderPath 分块文件路径 // 保留原作者写的块注释
     * @param chunkTotal 分块文件总数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private void clearChunkFiles(String chunkFileFolderPath,int chunkTotal){ // 定义方法 clearChunkFiles(...)
        Iterable<DeleteObject> objects =  Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> new DeleteObject(chunkFileFolderPath+ i)).collect(Collectors.toList());; // 把 Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> new DeleteObject(chunkFileFolderPath+ i)).collect(Collectors.toList()); 赋值给 objects
        RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucket_video).objects(objects).build(); // 把 RemoveObjectsArgs.builder().bucket(bucket_video).objects(objects).build() 的返回值赋给 removeObjectsArgs
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs); // 把 minioClient.removeObjects(removeObjectsArgs) 赋值给 results
        //要想真正删除 // 保留原作者写的行内注释
        results.forEach(f->{ // 定义方法 方法(...)
            try { // 尝试执行可能抛出异常的代码
                DeleteError deleteError = f.get(); // 把 f.get() 的返回值赋给 deleteError
            } catch (Exception e) { // 定义方法 catch(...)
                e.printStackTrace(); // 执行语句
            } // 代码块结束
        }); // 执行语句

    } // 代码块结束
    /** // 保留原作者写的块注释
     * 从minio下载文件 // 保留原作者写的块注释
     * @param bucket 桶 // 保留原作者写的块注释
     * @param objectName 对象名称 // 保留原作者写的块注释
     * @return 下载后的文件 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public File downloadFileFromMinIO(String bucket,String objectName){ // 定义方法 downloadFileFromMinIO(...)
        //临时文件 // 保留原作者写的行内注释
        File minioFile = null; // 把变量 minioFile 初始化为 null
        FileOutputStream outputStream = null; // 把变量 outputStream 初始化为 null
        try{ // 尝试执行可能抛出异常的代码
            InputStream stream = minioClient.getObject(GetObjectArgs.builder() // 代码逻辑
                    .bucket(bucket) // 代码逻辑
                    .object(objectName) // 代码逻辑
                    .build()); // 执行语句
            //创建临时文件 // 保留原作者写的行内注释
            minioFile=File.createTempFile("minio", ".merge"); // 把 File.createTempFile("minio", ".merge") 赋值给 minioFile
            outputStream = new FileOutputStream(minioFile); // 创建 FileOutputStream 对象并赋值给 outputStream
            IOUtils.copy(stream,outputStream); // 执行语句
            return minioFile; // 返回 minioFile
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
        }finally { // 代码逻辑
            if(outputStream!=null){ // 定义方法 方法(...)
                try { // 尝试执行可能抛出异常的代码
                    outputStream.close(); // 执行语句
                } catch (IOException e) { // 定义方法 catch(...)
                    e.printStackTrace(); // 执行语句
                } // 代码块结束
            } // 代码块结束
        } // 代码块结束
        return null; // 返回 null
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 得到合并后的文件的地址 // 保留原作者写的块注释
     * @param fileMd5 文件id即md5值 // 保留原作者写的块注释
     * @param fileExt 文件扩展名 // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String getFilePathByMd5(String fileMd5,String fileExt){ // 定义方法 getFilePathByMd5(...)
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt; // 返回   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt
    } // 代码块结束

    //得到分块文件的目录 // 保留原作者写的行内注释
    private String getChunkFileFolderPath(String fileMd5) { // 定义方法 getChunkFileFolderPath(...)
        return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + "chunk" + "/"; // 返回 fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + "chunk" + "/"
    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/jobhandler/SampleXxlJob.java

package com.xuecheng.media.service.jobhandler; // 声明类所在的包路径

import com.xxl.job.core.context.XxlJobHelper; // 导入 XxlJobHelper 类
import com.xxl.job.core.handler.annotation.XxlJob; // 导入 XxlJob 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.io.BufferedInputStream; // 导入 BufferedInputStream 类
import java.io.BufferedReader; // 导入 BufferedReader 类
import java.io.DataOutputStream; // 导入 DataOutputStream 类
import java.io.InputStreamReader; // 导入 InputStreamReader 类
import java.net.HttpURLConnection; // 导入 HttpURLConnection 类
import java.net.URL; // 导入 URL 类
import java.util.Arrays; // 导入 Arrays 类
import java.util.concurrent.TimeUnit; // 导入 TimeUnit 类

/** // 保留原作者写的块注释
 * XxlJob开发示例(Bean模式) // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * 开发步骤: // 保留原作者写的块注释
 *      1、任务开发:在Spring Bean实例中,开发Job方法; // 保留原作者写的块注释
 *      2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。 // 保留原作者写的块注释
 *      3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志; // 保留原作者写的块注释
 *      4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果; // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author xuxueli 2019-12-11 21:52:51 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component // 使用注解 @Component
public class SampleXxlJob { // 定义 class SampleXxlJob
    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class); // 把 LoggerFactory.getLogger(SampleXxlJob.class) 赋值给 logger


    /** // 保留原作者写的块注释
     * 1、简单任务示例(Bean模式) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("demoJobHandler") // 使用注解 @XxlJob("demoJobHandler")
    public void demoJobHandler() throws Exception { // 定义方法 demoJobHandler(...)
        System.out.println("处理视频......."); // 执行语句


    } // 代码块结束


    @XxlJob("demoJobHandler2") // 使用注解 @XxlJob("demoJobHandler2")
    public void demoJobHandler2() throws Exception { // 定义方法 demoJobHandler2(...)
        System.out.println("处理文档......."); // 执行语句

        // default success // 保留原作者写的行内注释
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 2、分片广播任务 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("shardingJobHandler") // 使用注解 @XxlJob("shardingJobHandler")
    public void shardingJobHandler() throws Exception { // 定义方法 shardingJobHandler(...)

        // 分片参数 // 保留原作者写的行内注释
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号,从0开始 // 把 XxlJobHelper.getShardIndex() 的返回值赋给 shardIndex
        int shardTotal = XxlJobHelper.getShardTotal();//执行器总数 // 把 XxlJobHelper.getShardTotal() 的返回值赋给 shardTotal

        System.out.println("shardIndex="+shardIndex+",shardTotal="+shardTotal); // 把 "+shardIndex+",shardTotal="+shardTotal) 赋值给 System.out.println("shardIndex

    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/jobhandler/VideoTask.java

package com.xuecheng.media.service.jobhandler; // 声明类所在的包路径

import com.xuecheng.base.utils.Mp4VideoUtil; // 导入 Mp4VideoUtil 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.service.MediaFileProcessService; // 导入 MediaFileProcessService 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import com.xxl.job.core.context.XxlJobHelper; // 导入 XxlJobHelper 类
import com.xxl.job.core.handler.annotation.XxlJob; // 导入 XxlJob 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.io.File; // 导入 File 类
import java.io.IOException; // 导入 IOException 类
import java.util.List; // 导入 List 类
import java.util.concurrent.*; // 导入 * 类

/** // 保留原作者写的块注释
 * 任务处理类 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Component // 使用注解 @Component
public class VideoTask { // 定义 class VideoTask

    @Autowired // 使用注解 @Autowired
    MediaFileProcessService mediaFileProcessService; // 执行语句

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句

    //ffmpeg的路径 // 保留原作者写的行内注释
    @Value("${videoprocess.ffmpegpath}") // 使用注解 @Value("${videoprocess.ffmpegpath}")
    private String ffmpegpath; // 执行语句

    /** // 保留原作者写的块注释
     * 视频处理任务 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("videoJobHandler") // 使用注解 @XxlJob("videoJobHandler")
    public void videoJobHandler() throws Exception { // 定义方法 videoJobHandler(...)

        // 分片参数 // 保留原作者写的行内注释
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号,从0开始 // 把 XxlJobHelper.getShardIndex() 的返回值赋给 shardIndex
        int shardTotal = XxlJobHelper.getShardTotal();//执行器总数 // 把 XxlJobHelper.getShardTotal() 的返回值赋给 shardTotal

        //确定cpu的核心数 // 保留原作者写的行内注释
        int processors = Runtime.getRuntime().availableProcessors(); // 把 Runtime.getRuntime().availableProcessors() 的返回值赋给 processors
        //查询待处理的任务 // 保留原作者写的行内注释
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, processors); // 把 mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, processors) 赋值给 mediaProcessList

        //任务数量 // 保留原作者写的行内注释
        int size = mediaProcessList.size(); // 把 mediaProcessList.size() 的返回值赋给 size
        log.debug("取到视频处理任务数:"+size); // 执行语句
        if(size<=0){ // 定义方法 方法(...)
            return; // 直接返回不带结果
        } // 代码块结束
        //创建一个线程池 // 保留原作者写的行内注释
        ExecutorService executorService = Executors.newFixedThreadPool(size); // 把 Executors.newFixedThreadPool(size) 赋值给 executorService
        //使用的计数器 // 保留原作者写的行内注释
        CountDownLatch countDownLatch = new CountDownLatch(size); // 创建 CountDownLatch 对象并赋值给 countDownLatch
        mediaProcessList.forEach(mediaProcess -> { // 定义方法 方法(...)
            //将任务加入线程池 // 保留原作者写的行内注释
            executorService.execute(()->{ // 定义方法 方法(...)
                try { // 尝试执行可能抛出异常的代码
                    //任务id // 保留原作者写的行内注释
                    Long taskId = mediaProcess.getId(); // 把 mediaProcess.getId() 的返回值赋给 taskId
                    //文件id就是md5 // 保留原作者写的行内注释
                    String fileId = mediaProcess.getFileId(); // 把 mediaProcess.getFileId() 的返回值赋给 fileId
                    //开启任务 // 保留原作者写的行内注释
                    boolean b = mediaFileProcessService.startTask(taskId); // 把 mediaFileProcessService.startTask(taskId) 赋值给 b
                    if (!b) { // 定义方法 方法(...)
                        log.debug("抢占任务失败,任务id:{}", taskId); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束

                    //桶 // 保留原作者写的行内注释
                    String bucket = mediaProcess.getBucket(); // 把 mediaProcess.getBucket() 的返回值赋给 bucket
                    //objectName // 保留原作者写的行内注释
                    String objectName = mediaProcess.getFilePath(); // 把 mediaProcess.getFilePath() 的返回值赋给 objectName

                    //下载minio视频到本地 // 保留原作者写的行内注释
                    File file = mediaFileService.downloadFileFromMinIO(bucket, objectName); // 把 mediaFileService.downloadFileFromMinIO(bucket, objectName) 赋值给 file
                    if (file == null) { // 定义方法 方法(...)
                        log.debug("下载视频出错,任务id:{},bucket:{},objectName:{}", taskId, bucket, objectName); // 执行语句
                        //保存任务处理失败的结果 // 保留原作者写的行内注释
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "下载视频到本地失败"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束

                    //源avi视频的路径 // 保留原作者写的行内注释
                    String video_path = file.getAbsolutePath(); // 把 file.getAbsolutePath() 的返回值赋给 video_path
                    //转换后mp4文件的名称 // 保留原作者写的行内注释
                    String mp4_name = fileId + ".mp4"; // 把 fileId + ".mp4" 赋值给 mp4_name
                    //转换后mp4文件的路径 // 保留原作者写的行内注释
                    //先创建一个临时文件,作为转换后的文件 // 保留原作者写的行内注释
                    File mp4File = null; // 把变量 mp4File 初始化为 null
                    try { // 尝试执行可能抛出异常的代码
                        mp4File = File.createTempFile("minio", ".mp4"); // 把 File.createTempFile("minio", ".mp4") 赋值给 mp4File
                    } catch (IOException e) { // 定义方法 catch(...)
                        log.debug("创建临时文件异常,{}", e.getMessage()); // 执行语句
                        //保存任务处理失败的结果 // 保留原作者写的行内注释
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "创建临时文件异常"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束
                    String mp4_path = mp4File.getAbsolutePath(); // 把 mp4File.getAbsolutePath() 的返回值赋给 mp4_path
                    //创建工具类对象 // 保留原作者写的行内注释
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath, video_path, mp4_name, mp4_path); // 创建 Mp4VideoUtil 对象并赋值给 videoUtil
                    //开始视频转换,成功将返回success,失败返回失败原因 // 保留原作者写的行内注释
                    String result = videoUtil.generateMp4(); // 把 videoUtil.generateMp4() 的返回值赋给 result
                    if (!result.equals("success")) { // 定义方法 方法(...)

                        log.debug("视频转码失败,原因:{},bucket:{},objectName:{},", result, bucket, objectName); // 执行语句
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, result); // 执行语句
                        return; // 直接返回不带结果

                    } // 代码块结束
                    //上传到minio // 保留原作者写的行内注释
                    boolean b1 = mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", bucket, objectName); // 把 mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", bucket, objectName) 赋值给 b1
                    if (!b1) { // 定义方法 方法(...)
                        log.debug("上传mp4到minio失败,taskid:{}", taskId); // 执行语句
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "上传mp4到minio失败"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束
                    //mp4文件的url // 保留原作者写的行内注释
                    String url = getFilePath(fileId, ".mp4"); // 把 getFilePath(fileId, ".mp4") 赋值给 url

                    //更新任务状态为成功 // 保留原作者写的行内注释
                    mediaFileProcessService.saveProcessFinishStatus(taskId, "2", fileId, url, "创建临时文件异常"); // 执行语句
                }finally { // 代码逻辑
                    //计算器减去1 // 保留原作者写的行内注释
                    countDownLatch.countDown(); // 执行语句
                } // 代码块结束

            }); // 执行语句

        }); // 执行语句

        //阻塞,指定最大限制的等待时间,阻塞最多等待一定的时间后就解除阻塞 // 保留原作者写的行内注释
        countDownLatch.await(30, TimeUnit.MINUTES); // 执行语句


    } // 代码块结束

    private String getFilePath(String fileMd5,String fileExt){ // 定义方法 getFilePath(...)
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt; // 返回   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/MediaFileProcessService.java

package com.xuecheng.media.service; // 声明类所在的包路径

import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类

import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 任务处理 // 保留原作者写的块注释
 * @date 2023/2/19 10:43 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFileProcessService { // 定义 interface MediaFileProcessService

    /** // 保留原作者写的块注释
     * @description 获取待处理任务 // 保留原作者写的块注释
     * @param shardIndex 分片序号 // 保留原作者写的块注释
     * @param shardTotal 分片总数 // 保留原作者写的块注释
     * @param count 获取记录数 // 保留原作者写的块注释
     * @return java.util.List<com.xuecheng.media.model.po.MediaProcess> // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/14 14:49 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public List<MediaProcess> getMediaProcessList(int shardIndex, int shardTotal, int count); // 执行语句

    /** // 保留原作者写的块注释
     *  开启一个任务 // 保留原作者写的块注释
     * @param id 任务id // 保留原作者写的块注释
     * @return true开启任务成功,false开启任务失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public boolean startTask(long id); // 执行语句


    /** // 保留原作者写的块注释
     * @description 保存任务结果 // 保留原作者写的块注释
     * @param taskId  任务id // 保留原作者写的块注释
     * @param status 任务状态 // 保留原作者写的块注释
     * @param fileId  文件id // 保留原作者写的块注释
     * @param url url // 保留原作者写的块注释
     * @param errorMsg 错误信息 // 保留原作者写的块注释
     * @return void // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/15 11:29 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    void saveProcessFinishStatus(Long taskId,String status,String fileId,String url,String errorMsg); // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/service/main/com/xuecheng/media/service/MediaFileService.java

package com.xuecheng.media.service; // 声明类所在的包路径

import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import io.minio.UploadObjectArgs; // 导入 UploadObjectArgs 类
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 类

import java.io.File; // 导入 File 类
import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @description 媒资文件管理业务类 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/9/10 8:55 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFileService { // 定义 interface MediaFileService

 //根据媒资id查询文件信息 // 保留原作者写的行内注释
 MediaFiles getFileById(String mediaId); // 执行语句

 /** // 保留原作者写的块注释
  * @description 媒资文件查询方法 // 保留原作者写的块注释
  * @param pageParams 分页参数 // 保留原作者写的块注释
  * @param queryMediaParamsDto 查询条件 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.PageResult<com.xuecheng.media.model.po.MediaFiles> // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/10 8:57 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 public PageResult<MediaFiles> queryMediaFiels(Long companyId,PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto); // 执行语句

 /** // 保留原作者写的块注释
  * 上传文件 // 保留原作者写的块注释
  * @param // 保留原作者写的块注释
  * companyId 机构id // 保留原作者写的块注释
  * @param uploadFileParamsDto 文件信息 // 保留原作者写的块注释
  * @param localFilePath 文件本地路径 // 保留原作者写的块注释
  * @param objectname 如果传入objectname要按objectname的目录去存储,如果不传就按年月日目录结构去存储 // 保留原作者写的块注释
  * @return UploadFileResultDto // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath,String objectname); // 执行语句

 public MediaFiles addMediaFilesToDb(Long companyId,String fileMd5,UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName); // 执行语句

 /** // 保留原作者写的块注释
  * 将文件上传到minio // 保留原作者写的块注释
  * @param localFilePath 文件本地路径 // 保留原作者写的块注释
  * @param mimeType 媒体类型 // 保留原作者写的块注释
  * @param bucket 桶 // 保留原作者写的块注释
  * @param objectName 对象名 // 保留原作者写的块注释
  * @return // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName); // 执行语句

 /** // 保留原作者写的块注释
  * @description 检查文件是否存在 // 保留原作者写的块注释
  * @param fileMd5 文件的md5 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse<java.lang.Boolean> false不存在,true存在 // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:38 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse<Boolean> checkFile(String fileMd5); // 执行语句

 /** // 保留原作者写的块注释
  * @description 检查分块是否存在 // 保留原作者写的块注释
  * @param fileMd5  文件的md5 // 保留原作者写的块注释
  * @param chunkIndex  分块序号 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse<java.lang.Boolean> false不存在,true存在 // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:39 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex); // 执行语句

 /** // 保留原作者写的块注释
  * @description 上传分块 // 保留原作者写的块注释
  * @param fileMd5  文件md5 // 保留原作者写的块注释
  * @param chunk  分块序号 // 保留原作者写的块注释
  * @param localChunkFilePath  分块文件本地路径 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:50 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse uploadChunk(String fileMd5,int chunk,String localChunkFilePath); // 执行语句


 /** // 保留原作者写的块注释
  * @description 合并分块 // 保留原作者写的块注释
  * @param companyId  机构id // 保留原作者写的块注释
  * @param fileMd5  文件md5 // 保留原作者写的块注释
  * @param chunkTotal 分块总和 // 保留原作者写的块注释
  * @param uploadFileParamsDto 文件信息 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:56 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse mergechunks(Long companyId,String fileMd5,int chunkTotal,UploadFileParamsDto uploadFileParamsDto); // 执行语句

 /** // 保留原作者写的块注释
  * 从minio下载文件 // 保留原作者写的块注释
  * @param bucket 桶 // 保留原作者写的块注释
  * @param objectName 对象名称 // 保留原作者写的块注释
  * @return 下载后的文件 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public File downloadFileFromMinIO(String bucket, String objectName); // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/service/resources/bootstrap.yml

spring: # Spring Boot 顶层配置
  application:
    name: media-service # 媒资服务注册名
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: redis-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: minio-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
  profiles:
    active: dev

文件:xuecheng-plus-media/service/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="180" packages="">
    <properties>
        <property name="logdir">logs</property>
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${PATTERN}"/>
        </Console>
        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>
        <RollingFile name="DebugAppender" fileName="${logdir}/info.log"
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true">
            <PatternLayout pattern="${PATTERN}"/>
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>
        <Async name="AsyncAppender" includeLocation="true">
            <AppenderRef ref="ErrorAppender"/>
            <AppenderRef ref="DebugAppender"/>
        </Async>
    </Appenders>
    <Loggers>
        <Root level="DEBUG" includeLocation="true">
            <AppenderRef ref="AsyncAppender"/>
            <AppenderRef ref="Console"/>
            <AppenderRef ref="DebugAppender"/>
        </Root>
    </Loggers>
</Configuration>

文件:xuecheng-plus-media/service_pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>xuecheng-plus-media</artifactId>
        <groupId>com.xuecheng</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>xuecheng-plus-media-service</artifactId>
    <dependencies>
       <dependency>
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
       </dependency>
       <dependency>
           <groupId>com.xuecheng</groupId>
           <artifactId>xuecheng-plus-media-model</artifactId>
           <version>0.0.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>com.xuecheng</groupId>
           <artifactId>xuecheng-plus-base</artifactId>
           <version>0.0.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>io.minio</groupId>
           <artifactId>minio</artifactId>
           <version>${minio.version}</version>
       </dependency>
       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-boot-starter</artifactId>
       </dependency>
       <dependency>
           <groupId>com.xuxueli</groupId>
           <artifactId>xxl-job-core</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-log4j2</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
    </dependencies>
</project>

文件:xuecheng-plus-media/xuecheng-plus-media-api/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-media</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-media-api</artifactId> <!-- SQL 语句片段 -->
    <name>xuecheng-plus-media-api</name> <!-- SQL 语句片段 -->
    <description>xuecheng-plus-media-api</description> <!-- SQL 语句片段 -->

    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-media-model</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-media-service</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!--cloud的基础环境包-->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-context</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 的 Spring Web MVC 集成 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-web</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-validation</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 对 LocalDateTime
          boot-starter-web自动引入 <!-- SQL 语句片段 -->
          --> <!-- SQL 语句片段 -->
       <!-- <dependency>
            <groupId>com.fasterxml.jackson.module</groupId> <!-- SQL 语句片段 -->
            <artifactId>jackson-module-parameter-names</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.fasterxml.jackson.datatype</groupId> <!-- SQL 语句片段 -->
            <artifactId>jackson-datatype-jdk8</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.fasterxml.jackson.datatype</groupId> <!-- SQL 语句片段 -->
            <artifactId>jackson-datatype-jsr310</artifactId> <!-- SQL 语句片段 -->
        </dependency>--> <!-- SQL 语句片段 -->

        <!--<dependency>
            <groupId>org.apache.commons</groupId> <!-- SQL 语句片段 -->
            <artifactId>commons-pool2</artifactId> <!-- SQL 语句片段 -->
        </dependency>--> <!-- SQL 语句片段 -->
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
            <exclusions> <!-- SQL 语句片段 -->
                <exclusion> <!-- SQL 语句片段 -->
                    <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                    <artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
                </exclusion> <!-- SQL 语句片段 -->
            </exclusions> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 log4j2 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 swagger -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.spring4all</groupId> <!-- SQL 语句片段 -->
            <artifactId>swagger-spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->


    </dependencies> <!-- SQL 语句片段 -->

    <build> <!-- SQL 语句片段 -->
        <finalName>${project.artifactId}-${project.version}</finalName> <!-- SQL 语句片段 -->
        <plugins> <!-- SQL 语句片段 -->
            <plugin> <!-- SQL 语句片段 -->
                <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                <artifactId>spring-boot-maven-plugin</artifactId> <!-- SQL 语句片段 -->
                <version>${spring-boot.version}</version> <!-- SQL 语句片段 -->
                <executions> <!-- SQL 语句片段 -->
                    <execution> <!-- SQL 语句片段 -->
                        <goals> <!-- SQL 语句片段 -->
                            <goal>repackage</goal> <!-- SQL 语句片段 -->
                        </goals> <!-- SQL 语句片段 -->
                    </execution> <!-- SQL 语句片段 -->
                </executions> <!-- SQL 语句片段 -->
            </plugin> <!-- SQL 语句片段 -->
            <plugin> <!-- SQL 语句片段 -->
                <groupId>com.spotify</groupId> <!-- SQL 语句片段 -->
                <artifactId>docker-maven-plugin</artifactId> <!-- SQL 语句片段 -->
                <version>1.2.2</version> <!-- SQL 语句片段 -->
                <configuration> <!-- SQL 语句片段 -->
                    <!--修改imageName节点的内容,改为私有仓库地址和端口,再加上镜像id和 TAG,我们要直接传到私服-->
                    <!--配置最后生成的镜像名,docker images里的,我们这边取项目名:版本-->
                    <!--<imageName>${project.artifactId}:${project.version}</imageName>-->
                    <imageName>192.168.101.65:5000/${project.artifactId}:${project.version}</imageName> <!-- SQL 语句片段 -->
                    <!--也可以通过以下方式定义image的tag信息。 -->
                    <!-- <imageTags>
                         <imageTag>${project.version}</imageTag> <!-- SQL 语句片段 -->
                         &lt;!&ndash;build 时强制覆盖 tag,配合 imageTags 使用&ndash;&gt; <!-- SQL 语句片段 -->
                         <forceTags>true</forceTags> <!-- SQL 语句片段 -->
                         &lt;!&ndash;build 完成后,push 指定 tag 的镜像,配合 imageTags 使用&ndash;&gt; <!-- SQL 语句片段 -->
                         <pushImageTag>true</pushImageTag> <!-- SQL 语句片段 -->
                     </imageTags>--> <!-- SQL 语句片段 -->
                    <baseImage>java:8u20</baseImage> <!-- SQL 语句片段 -->
                    <maintainer>docker_maven [email protected]</maintainer> <!-- SQL 语句片段 -->
                    <workdir>/root</workdir> <!-- SQL 语句片段 -->
                    <cmd>["java", "-version"]</cmd> <!-- SQL 语句片段 -->
                    <!--来指明Dockerfile文件的所在目录,如果配置了dockerDirectory则忽略baseImage,maintainer等配置-->
                    <!--<dockerDirectory>./</dockerDirectory>-->
                    <!--2375是docker的远程端口,插件生成镜像时连接docker,这里需要指定docker远程端口-->
                    <dockerHost>http://192.168.101.65:2375</dockerHost> <!-- SQL 语句片段 -->
                    <!--入口点,project.build.finalName就是project标签下的build标签下 的filename标签内容,testDocker-->
                    <!--相当于启动容器后,会自动执行java -jar ...-->
                    <entryPoint>["java", "-Dfile.encoding=utf-8","-jar", "/root/${project.build.finalName}.jar"]</entryPoint> <!-- SQL 语句片段 -->
                    <!--是否推送到docker私有仓库,旧版本插件要配置maven的settings文件。 -->
                    <pushImage>true</pushImage> <!-- SQL 语句片段 -->
                    <registryUrl>192.168.101.65:5000</registryUrl>  <!-- 这里是复制 jar 包到 docker 容器指定目录配置 --> <!-- SQL 语句片段 -->
                    <resources> <!-- SQL 语句片段 -->
                        <resource> <!-- SQL 语句片段 -->
                            <targetPath>/root</targetPath> <!-- SQL 语句片段 -->
                            <directory>${project.build.directory}</directory> <!-- SQL 语句片段 -->
                            <!--把哪个文件上传到docker,相当于Dockerfile里的add app.jar /-->
                            <include>${project.build.finalName}.jar</include> <!-- 引用公共 SQL 片段 -->
                        </resource> <!-- SQL 语句片段 -->
                    </resources> <!-- SQL 语句片段 -->
                </configuration> <!-- SQL 语句片段 -->
            </plugin> <!-- SQL 语句片段 -->
        </plugins> <!-- SQL 语句片段 -->
    </build> <!-- SQL 语句片段 -->
</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/media/api/BigFilesController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.PostMapping; // 导入 PostMapping 类
import org.springframework.web.bind.annotation.RequestParam; // 导入 RequestParam 类
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 类
import org.springframework.web.multipart.MultipartFile; // 导入 MultipartFile 类

import java.io.File; // 导入 File 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 上传视频 // 保留原作者写的块注释
 * @date 2023/2/18 10:34 // 保留原作者写的块注释
 */ // 保留原作者写的块注释

@Api(value = "大文件上传接口", tags = "大文件上传接口") // 使用注解 @Api(value = "大文件上传接口", tags = "大文件上传接口")
@RestController // 使用注解 @RestController
public class BigFilesController { // 定义 class BigFilesController

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句


    @ApiOperation(value = "文件上传前检查文件") // 使用注解 @ApiOperation(value = "文件上传前检查文件")
    @PostMapping("/upload/checkfile") // 使用注解 @PostMapping("/upload/checkfile")
    public RestResponse<Boolean> checkfile( // 代码逻辑
            @RequestParam("fileMd5") String fileMd5 // 使用注解 @RequestParam("fileMd5") String fileMd5
    ) throws Exception { // 代码逻辑
        RestResponse<Boolean> booleanRestResponse = mediaFileService.checkFile(fileMd5); // 把 mediaFileService.checkFile(fileMd5) 赋值给 booleanRestResponse
        return booleanRestResponse; // 返回 booleanRestResponse
    } // 代码块结束


    @ApiOperation(value = "分块文件上传前的检测") // 使用注解 @ApiOperation(value = "分块文件上传前的检测")
    @PostMapping("/upload/checkchunk") // 使用注解 @PostMapping("/upload/checkchunk")
    public RestResponse<Boolean> checkchunk(@RequestParam("fileMd5") String fileMd5, // 代码逻辑
                                            @RequestParam("chunk") int chunk) throws Exception { // 使用注解 @RequestParam("chunk") int chunk) throws Exception {
        RestResponse<Boolean> booleanRestResponse = mediaFileService.checkChunk(fileMd5,chunk); // 把 mediaFileService.checkChunk(fileMd5,chunk) 赋值给 booleanRestResponse
        return booleanRestResponse; // 返回 booleanRestResponse
    } // 代码块结束

    @ApiOperation(value = "上传分块文件") // 使用注解 @ApiOperation(value = "上传分块文件")
    @PostMapping("/upload/uploadchunk") // 使用注解 @PostMapping("/upload/uploadchunk")
    public RestResponse uploadchunk(@RequestParam("file") MultipartFile file, // 代码逻辑
                                    @RequestParam("fileMd5") String fileMd5, // 使用注解 @RequestParam("fileMd5") String fileMd5,
                                    @RequestParam("chunk") int chunk) throws Exception { // 使用注解 @RequestParam("chunk") int chunk) throws Exception {

        //创建一个临时文件 // 保留原作者写的行内注释
        File tempFile = File.createTempFile("minio", ".temp"); // 把 File.createTempFile("minio", ".temp") 赋值给 tempFile
        file.transferTo(tempFile); // 执行语句
        //文件路径 // 保留原作者写的行内注释
        String localFilePath = tempFile.getAbsolutePath(); // 把 tempFile.getAbsolutePath() 的返回值赋给 localFilePath

        RestResponse restResponse = mediaFileService.uploadChunk(fileMd5, chunk, localFilePath); // 把 mediaFileService.uploadChunk(fileMd5, chunk, localFilePath) 赋值给 restResponse

        return restResponse; // 返回 restResponse
    } // 代码块结束

    @ApiOperation(value = "合并文件") // 使用注解 @ApiOperation(value = "合并文件")
    @PostMapping("/upload/mergechunks") // 使用注解 @PostMapping("/upload/mergechunks")
    public RestResponse mergechunks(@RequestParam("fileMd5") String fileMd5, // 代码逻辑
                                    @RequestParam("fileName") String fileName, // 使用注解 @RequestParam("fileName") String fileName,
                                    @RequestParam("chunkTotal") int chunkTotal) throws Exception { // 使用注解 @RequestParam("chunkTotal") int chunkTotal) throws Exception {
        Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
        //文件信息对象 // 保留原作者写的行内注释
        UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto(); // 创建 UploadFileParamsDto 对象并赋值给 uploadFileParamsDto
        uploadFileParamsDto.setFilename(fileName); // 执行语句
        uploadFileParamsDto.setTags("视频文件"); // 执行语句
        uploadFileParamsDto.setFileType("001002"); // 执行语句
        RestResponse restResponse = mediaFileService.mergechunks(1232141425L, fileMd5, chunkTotal, uploadFileParamsDto); // 把 mediaFileService.mergechunks(1232141425L, fileMd5, chunkTotal, uploadFileParamsDto) 赋值给 restResponse
        return restResponse; // 返回 restResponse

    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/media/api/MediaFilesController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.http.MediaType; // 导入 MediaType 类
import org.springframework.web.bind.annotation.*; // 导入 * 类
import org.springframework.web.multipart.MultipartFile; // 导入 MultipartFile 类

import java.io.File; // 导入 File 类
import java.io.IOException; // 导入 IOException 类

/** // 保留原作者写的块注释
 * @description 媒资文件管理接口 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/9/6 11:29 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 @Api(value = "媒资文件管理接口",tags = "媒资文件管理接口") // 使用注解 @Api(value = "媒资文件管理接口",tags = "媒资文件管理接口")
 @RestController // 使用注解 @RestController
public class MediaFilesController { // 定义 class MediaFilesController


  @Autowired // 使用注解 @Autowired
  MediaFileService mediaFileService; // 执行语句


 @ApiOperation("媒资列表查询接口") // 使用注解 @ApiOperation("媒资列表查询接口")
 @PostMapping("/files") // 使用注解 @PostMapping("/files")
 public PageResult<MediaFiles> list(PageParams pageParams, @RequestBody QueryMediaParamsDto queryMediaParamsDto){ // 定义方法 list(...)
  Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
  return mediaFileService.queryMediaFiels(companyId,pageParams,queryMediaParamsDto); // 返回 mediaFileService.queryMediaFiels(companyId,pageParams,queryMediaParamsDto)

 } // 代码块结束

 @ApiOperation("上传图片") // 使用注解 @ApiOperation("上传图片")
 @RequestMapping(value = "/upload/coursefile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE) // 使用注解 @RequestMapping(value = "/upload/coursefile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public UploadFileResultDto upload(@RequestPart("filedata")MultipartFile filedata, // 代码逻辑
                                  @RequestParam(value= "objectName",required=false) String objectName) throws IOException { // 使用注解 @RequestParam(value= "objectName",required=false) String objectName) throws IOException {

    //准备上传文件的信息 // 保留原作者写的行内注释
     UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto(); // 创建 UploadFileParamsDto 对象并赋值给 uploadFileParamsDto
     //原始文件名称 // 保留原作者写的行内注释
     uploadFileParamsDto.setFilename(filedata.getOriginalFilename()); // 执行语句
     //文件大小 // 保留原作者写的行内注释
     uploadFileParamsDto.setFileSize(filedata.getSize()); // 执行语句
     //文件类型 // 保留原作者写的行内注释
     uploadFileParamsDto.setFileType("001001"); // 执行语句
     //创建一个临时文件 // 保留原作者写的行内注释
     File tempFile = File.createTempFile("minio", ".temp"); // 把 File.createTempFile("minio", ".temp") 赋值给 tempFile
     filedata.transferTo(tempFile); // 执行语句
     Long companyId = 1232141425L; // 把 1232141425L 赋值给 companyId
    //文件路径 // 保留原作者写的行内注释
     String localFilePath = tempFile.getAbsolutePath(); // 把 tempFile.getAbsolutePath() 的返回值赋给 localFilePath

     //调用service上传图片 // 保留原作者写的行内注释
     UploadFileResultDto uploadFileResultDto = mediaFileService.uploadFile(companyId, uploadFileParamsDto, localFilePath,objectName); // 把 mediaFileService.uploadFile(companyId, uploadFileParamsDto, localFilePath,objectName) 赋值给 uploadFileResultDto

     return uploadFileResultDto; // 返回 uploadFileResultDto
 } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/media/api/MediaOpenController.java

package com.xuecheng.media.api; // 声明类所在的包路径

import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.swagger.annotations.Api; // 导入 Api 类
import io.swagger.annotations.ApiOperation; // 导入 ApiOperation 类
import org.apache.commons.lang3.StringUtils; // 导入 StringUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 类
import org.springframework.web.bind.annotation.PathVariable; // 导入 PathVariable 类
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 类
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/21 10:35 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
// 视频播放页面接口 // 保留原作者写的行内注释
@Api(value = "媒资文件管理接口", tags = "媒资文件管理接口") // 使用注解 @Api(value = "媒资文件管理接口", tags = "媒资文件管理接口")
@RestController // 使用注解 @RestController
@RequestMapping("/open") // 使用注解 @RequestMapping("/open")
public class MediaOpenController { // 定义 class MediaOpenController

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句

    @ApiOperation("预览文件") // 使用注解 @ApiOperation("预览文件")
    @GetMapping("/preview/{mediaId}") // 使用注解 @GetMapping("/preview/{mediaId}")
    public RestResponse<String> getPlayUrlByMediaId(@PathVariable String mediaId) { // 定义方法 getPlayUrlByMediaId(...)
        //查询媒资文件信息 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFileService.getFileById(mediaId); // 把 mediaFileService.getFileById(mediaId) 赋值给 mediaFiles

        if (mediaFiles == null) { // 定义方法 方法(...)
            return RestResponse.validfail("找不到视频"); // 返回 RestResponse.validfail("找不到视频")
        } // 代码块结束
        //取出视频播放地址 // 保留原作者写的行内注释
        String url = mediaFiles.getUrl(); // 把 mediaFiles.getUrl() 的返回值赋给 url
        if (StringUtils.isEmpty(url)) { // 定义方法 方法(...)
            return RestResponse.validfail("该视频正在处理中"); // 返回 RestResponse.validfail("该视频正在处理中")
        } // 代码块结束
        return RestResponse.success(mediaFiles.getUrl()); // 返回 RestResponse.success(mediaFiles.getUrl())
    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/MediaApplication.java

package com.xuecheng; // 声明类所在的包路径


import com.spring4all.swagger.EnableSwagger2Doc; // 导入 EnableSwagger2Doc 类
import org.springframework.boot.SpringApplication; // 导入 SpringApplication 类
import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入 SpringBootApplication 类

@EnableSwagger2Doc // 使用注解 @EnableSwagger2Doc
@SpringBootApplication // 使用注解 @SpringBootApplication
public class MediaApplication { // 定义 class MediaApplication
	public static void main(String[] args) { // 定义方法 main(...)
		SpringApplication.run(MediaApplication.class, args); // 执行语句
	} // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/resources/bootstrap.yml

#微服务配置
spring:
  application:
    name: media-api
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
        extension-configs:
          - data-id: media-service-${spring.profiles.active}.yaml
            group: xuecheng-plus-project
            refresh: true
        shared-configs:
          - data-id: swagger-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
          - data-id: logging-${spring.profiles.active}.yaml
            group: xuecheng-plus-common
            refresh: true
  profiles:
    active: dev


文件:xuecheng-plus-media/xuecheng-plus-media-api/src/main/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
    <properties> <!-- SQL 语句片段 -->
        <property name="logdir">logs</property> <!-- SQL 语句片段 -->
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
    </properties> <!-- SQL 语句片段 -->
    <Appenders> <!-- SQL 语句片段 -->
        <Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
        </Console> <!-- SQL 语句片段 -->

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Async> <!-- SQL 语句片段 -->
    </Appenders> <!-- SQL 语句片段 -->
    
    <Loggers> <!-- SQL 语句片段 -->
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        
        <logger name="RocketmqCommon"  level="INFO" > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqRemoting" level="INFO"  > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Root> <!-- SQL 语句片段 -->
    </Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/xuecheng-plus-media-model/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-media</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-media-model</artifactId> <!-- SQL 语句片段 -->
    <name>xuecheng-plus-media-model</name> <!-- SQL 语句片段 -->
    <description>xuecheng-plus-media-model</description> <!-- SQL 语句片段 -->

    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-base</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!--存在mybatisplus注解添加相关注解保证不报错-->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-annotation</artifactId> <!-- SQL 语句片段 -->
            <version>${mybatis-plus-boot-starter.version}</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-core</artifactId> <!-- SQL 语句片段 -->
            <version>${mybatis-plus-boot-starter.version}</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.projectlombok</groupId> <!-- SQL 语句片段 -->
            <artifactId>lombok</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
    </dependencies> <!-- SQL 语句片段 -->

</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/dto/QueryMediaParamsDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import io.swagger.annotations.ApiModelProperty; // 导入 ApiModelProperty 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 媒资文件查询请求模型类 // 保留原作者写的块注释
 * @date 2022/9/10 8:53 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class QueryMediaParamsDto { // 定义 class QueryMediaParamsDto

    @ApiModelProperty("媒资文件名称") // 使用注解 @ApiModelProperty("媒资文件名称")
    private String filename; // 执行语句
    @ApiModelProperty("媒资类型") // 使用注解 @ApiModelProperty("媒资类型")
    private String fileType; // 执行语句
    @ApiModelProperty("审核状态") // 使用注解 @ApiModelProperty("审核状态")
    private String auditStatus; // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/dto/UploadFileParamsDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 文件信息 // 保留原作者写的块注释
 * @date 2023/2/17 15:09 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class UploadFileParamsDto { // 定义 class UploadFileParamsDto

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句


    /** // 保留原作者写的块注释
     * 文件类型(文档,音频,视频) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileType; // 执行语句
    /** // 保留原作者写的块注释
     * 文件大小 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long fileSize; // 执行语句

    /** // 保留原作者写的块注释
     * 标签 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String tags; // 执行语句
    /** // 保留原作者写的块注释
     * 上传人 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String username; // 执行语句
    /** // 保留原作者写的块注释
     * 备注 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String remark; // 执行语句

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/dto/UploadFileResultDto.java

package com.xuecheng.media.model.dto; // 声明类所在的包路径

import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/17 15:06 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
public class UploadFileResultDto extends MediaFiles { // 定义 class UploadFileResultDto

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/po/MediaFiles.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 * 媒资信息 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("media_files") // 使用注解 @TableName("media_files")
public class MediaFiles implements Serializable { // 定义 class MediaFiles

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 主键 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableId(value = "id", type = IdType.ASSIGN_ID) // 使用注解 @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 机构ID // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long companyId; // 执行语句

    /** // 保留原作者写的块注释
     * 机构名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String companyName; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 文件类型(文档,音频,视频) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileType; // 执行语句

    /** // 保留原作者写的块注释
     * 标签 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String tags; // 执行语句

    /** // 保留原作者写的块注释
     * 存储目录 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    /** // 保留原作者写的块注释
     * 存储路径 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filePath; // 执行语句


    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句


    /** // 保留原作者写的块注释
     * 上传人 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String username; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 修改时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT_UPDATE) // 使用注解 @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime changeDate; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 备注 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String remark; // 执行语句

    /** // 保留原作者写的块注释
     * 审核状态 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String auditStatus; // 执行语句

    /** // 保留原作者写的块注释
     * 审核意见 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String auditMind; // 执行语句

    /** // 保留原作者写的块注释
     * 文件大小 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Long fileSize; // 执行语句

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/po/MediaProcess.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类
import lombok.ToString; // 导入 ToString 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@ToString // 使用注解 @ToString
@TableName("media_process") // 使用注解 @TableName("media_process")
public class MediaProcess implements Serializable { // 定义 class MediaProcess

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 存储源 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    private String filePath; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 完成时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime finishDate; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句

    /** // 保留原作者写的块注释
     * 失败原因 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String errormsg; // 执行语句

    /** // 保留原作者写的块注释
     * 失败次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private int failCount; // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/po/MediaProcessHistory.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.*; // 导入 * 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("media_process_history") // 使用注解 @TableName("media_process_history")
public class MediaProcessHistory implements Serializable { // 定义 class MediaProcessHistory

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    @TableId(value = "id", type = IdType.AUTO) // 使用注解 @TableId(value = "id", type = IdType.AUTO)
    private Long id; // 执行语句

    /** // 保留原作者写的块注释
     * 文件标识 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String fileId; // 执行语句

    /** // 保留原作者写的块注释
     * 文件名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String filename; // 执行语句

    /** // 保留原作者写的块注释
     * 存储源 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String bucket; // 执行语句

    private String filePath; // 执行语句

    /** // 保留原作者写的块注释
     * 状态,1:未处理,视频处理完成更新为2 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String status; // 执行语句

    /** // 保留原作者写的块注释
     * 上传时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @TableField(fill = FieldFill.INSERT) // 使用注解 @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createDate; // 执行语句

    /** // 保留原作者写的块注释
     * 完成时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime finishDate; // 执行语句

    /** // 保留原作者写的块注释
     * 媒资文件访问地址 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String url; // 执行语句
    /** // 保留原作者写的块注释
     * 失败原因 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String errormsg; // 执行语句

    /** // 保留原作者写的块注释
     * 失败次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private int failCount; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/po/MqMessage.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("mq_message") // 使用注解 @TableName("mq_message")
public class MqMessage implements Serializable { // 定义 class MqMessage

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 消息id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 消息类型代码 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String messageType; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey1; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey2; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey3; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqHost; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列端口 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer mqPort; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列虚拟主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqVirtualhost; // 执行语句

    /** // 保留原作者写的块注释
     * 队列名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqQueue; // 执行语句

    /** // 保留原作者写的块注释
     * 通知次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer informNum; // 执行语句

    /** // 保留原作者写的块注释
     * 处理状态,0:初始,1:成功,2:失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer state; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnfailureDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnsuccessDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败内容 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String returnfailureMsg; // 执行语句

    /** // 保留原作者写的块注释
     * 最近通知时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime informDate; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-model/src/main/java/com/xuecheng/media/model/po/MqMessageHistory.java

package com.xuecheng.media.model.po; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 类
import lombok.Data; // 导入 Data 类

import java.io.Serializable; // 导入 Serializable 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Data // 使用注解 @Data
@TableName("mq_message_history") // 使用注解 @TableName("mq_message_history")
public class MqMessageHistory implements Serializable { // 定义 class MqMessageHistory

    private static final long serialVersionUID = 1L; // 把 1L 赋值给 serialVersionUID

    /** // 保留原作者写的块注释
     * 消息id // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String id; // 执行语句

    /** // 保留原作者写的块注释
     * 消息类型代码 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String messageType; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey1; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey2; // 执行语句

    /** // 保留原作者写的块注释
     * 关联业务信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String businessKey3; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqHost; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列端口 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer mqPort; // 执行语句

    /** // 保留原作者写的块注释
     * 消息队列虚拟主机 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqVirtualhost; // 执行语句

    /** // 保留原作者写的块注释
     * 队列名称 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String mqQueue; // 执行语句

    /** // 保留原作者写的块注释
     * 通知次数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer informNum; // 执行语句

    /** // 保留原作者写的块注释
     * 处理状态,0:初始,1:成功,2:失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private Integer state; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnfailureDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复成功时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime returnsuccessDate; // 执行语句

    /** // 保留原作者写的块注释
     * 回复失败内容 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String returnfailureMsg; // 执行语句

    /** // 保留原作者写的块注释
     * 最近通知时间 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private LocalDateTime informDate; // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/pom.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!-- SQL 语句片段 -->
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- SQL 语句片段 -->
    <modelVersion>4.0.0</modelVersion> <!-- SQL 语句片段 -->
    <parent> <!-- SQL 语句片段 -->
        <artifactId>xuecheng-plus-media</artifactId> <!-- SQL 语句片段 -->
        <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
        <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
    </parent> <!-- SQL 语句片段 -->
    <artifactId>xuecheng-plus-media-service</artifactId> <!-- SQL 语句片段 -->
    <name>xuecheng-plus-media-service</name> <!-- SQL 语句片段 -->
    <description>xuecheng-plus-media-service</description> <!-- SQL 语句片段 -->

    <dependencies> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.alibaba.cloud</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuecheng</groupId> <!-- SQL 语句片段 -->
            <artifactId>xuecheng-plus-media-model</artifactId> <!-- SQL 语句片段 -->
            <version>0.0.1-SNAPSHOT</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- MySQL 驱动 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>mysql</groupId> <!-- SQL 语句片段 -->
            <artifactId>mysql-connector-java</artifactId> <!-- SQL 语句片段 -->
            <scope>runtime</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- mybatis plus的依赖 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.baomidou</groupId> <!-- SQL 语句片段 -->
            <artifactId>mybatis-plus-boot-starter</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- Spring Boot 集成 Junit -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-test</artifactId> <!-- SQL 语句片段 -->
            <scope>test</scope> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <!-- 排除 Spring Boot 依赖的日志包冲突 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter</artifactId> <!-- SQL 语句片段 -->
            <exclusions> <!-- SQL 语句片段 -->
                <exclusion> <!-- SQL 语句片段 -->
                    <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
                    <artifactId>spring-boot-starter-logging</artifactId> <!-- SQL 语句片段 -->
                </exclusion> <!-- SQL 语句片段 -->
            </exclusions> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

        <!-- Spring Boot 集成 log4j2 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>org.springframework.boot</groupId> <!-- SQL 语句片段 -->
            <artifactId>spring-boot-starter-log4j2</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>io.minio</groupId> <!-- SQL 语句片段 -->
            <artifactId>minio</artifactId> <!-- SQL 语句片段 -->
            <version>8.4.3</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.squareup.okhttp3</groupId> <!-- SQL 语句片段 -->
            <artifactId>okhttp</artifactId> <!-- SQL 语句片段 -->
            <version>4.8.1</version> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->
        <dependency> <!-- SQL 语句片段 -->
            <groupId>com.xuxueli</groupId> <!-- SQL 语句片段 -->
            <artifactId>xxl-job-core</artifactId> <!-- SQL 语句片段 -->
        </dependency> <!-- SQL 语句片段 -->

    </dependencies> <!-- SQL 语句片段 -->

</project> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/config/MinioConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import io.minio.MinioClient; // 导入 MinioClient 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2023/2/17 15:00 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class MinioConfig { // 定义 class MinioConfig
 @Value("${minio.endpoint}") // 使用注解 @Value("${minio.endpoint}")
 private String endpoint; // 执行语句
 @Value("${minio.accessKey}") // 使用注解 @Value("${minio.accessKey}")
 private String accessKey; // 执行语句
 @Value("${minio.secretKey}") // 使用注解 @Value("${minio.secretKey}")
 private String secretKey; // 执行语句

 @Bean // 使用注解 @Bean
 public MinioClient minioClient() { // 定义方法 minioClient(...)

  MinioClient minioClient = // 代码逻辑
          MinioClient.builder() // 代码逻辑
                  .endpoint(endpoint) // 代码逻辑
                  .credentials(accessKey, secretKey) // 代码逻辑
                  .build(); // 执行语句
  return minioClient; // 返回 minioClient
 } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/config/MybatisPlusConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import com.baomidou.mybatisplus.annotation.DbType; // 导入 DbType 类
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; // 导入 MybatisPlusInterceptor 类
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; // 导入 PaginationInnerInterceptor 类
import org.mybatis.spring.annotation.MapperScan; // 导入 MapperScan 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * <P> // 保留原作者写的块注释
 * 		Mybatis-Plus 配置 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
@MapperScan("com.xuecheng.media.mapper") // 使用注解 @MapperScan("com.xuecheng.media.mapper")
public class MybatisPlusConfig { // 定义 class MybatisPlusConfig
	/** // 保留原作者写的块注释
	 * 新的分页插件 // 保留原作者写的块注释
	 * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false // 保留原作者写的块注释
	 * 避免缓存出现问题(该属性会在旧插件移除后一同移除) // 保留原作者写的块注释
	 */ // 保留原作者写的块注释
	@Bean // 使用注解 @Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() { // 定义方法 mybatisPlusInterceptor(...)
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建 MybatisPlusInterceptor 对象并赋值给 interceptor
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 执行语句
		return interceptor; // 返回 interceptor
	} // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/config/XxlJobConfig.java

package com.xuecheng.media.config; // 声明类所在的包路径

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; // 导入 XxlJobSpringExecutor 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.context.annotation.Bean; // 导入 Bean 类
import org.springframework.context.annotation.Configuration; // 导入 Configuration 类

/** // 保留原作者写的块注释
 * xxl-job config // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author xuxueli 2017-04-28 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Configuration // 使用注解 @Configuration
public class XxlJobConfig { // 定义 class XxlJobConfig
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); // 把 LoggerFactory.getLogger(XxlJobConfig.class) 赋值给 logger

    @Value("${xxl.job.admin.addresses}") // 使用注解 @Value("${xxl.job.admin.addresses}")
    private String adminAddresses; // 执行语句

    @Value("${xxl.job.accessToken}") // 使用注解 @Value("${xxl.job.accessToken}")
    private String accessToken; // 执行语句

    @Value("${xxl.job.executor.appname}") // 使用注解 @Value("${xxl.job.executor.appname}")
    private String appname; // 执行语句

    @Value("${xxl.job.executor.address}") // 使用注解 @Value("${xxl.job.executor.address}")
    private String address; // 执行语句

    @Value("${xxl.job.executor.ip}") // 使用注解 @Value("${xxl.job.executor.ip}")
    private String ip; // 执行语句

    @Value("${xxl.job.executor.port}") // 使用注解 @Value("${xxl.job.executor.port}")
    private int port; // 执行语句

    @Value("${xxl.job.executor.logpath}") // 使用注解 @Value("${xxl.job.executor.logpath}")
    private String logPath; // 执行语句

    @Value("${xxl.job.executor.logretentiondays}") // 使用注解 @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays; // 执行语句


    @Bean // 使用注解 @Bean
    public XxlJobSpringExecutor xxlJobExecutor() { // 定义方法 xxlJobExecutor(...)
        logger.info(">>>>>>>>>>> xxl-job config init."); // 执行语句
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); // 创建 XxlJobSpringExecutor 对象并赋值给 xxlJobSpringExecutor
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses); // 执行语句
        xxlJobSpringExecutor.setAppname(appname); // 执行语句
        xxlJobSpringExecutor.setAddress(address); // 执行语句
        xxlJobSpringExecutor.setIp(ip); // 执行语句
        xxlJobSpringExecutor.setPort(port); // 执行语句
        xxlJobSpringExecutor.setAccessToken(accessToken); // 执行语句
        xxlJobSpringExecutor.setLogPath(logPath); // 执行语句
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); // 执行语句

        return xxlJobSpringExecutor; // 返回 xxlJobSpringExecutor
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP; // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      1、引入依赖: // 保留原作者写的块注释
     *          <dependency> // 保留原作者写的块注释
     *             <groupId>org.springframework.cloud</groupId> // 保留原作者写的块注释
     *             <artifactId>spring-cloud-commons</artifactId> // 保留原作者写的块注释
     *             <version>${version}</version> // 保留原作者写的块注释
     *         </dependency> // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      2、配置文件,或者容器启动变量 // 保留原作者写的块注释
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.' // 保留原作者写的块注释
     * // 保留原作者写的块注释
     *      3、获取IP // 保留原作者写的块注释
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); // 保留原作者写的块注释
     */ // 保留原作者写的块注释


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaFilesMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 * 媒资信息 Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFilesMapper extends BaseMapper<MediaFiles> { // 定义 interface MediaFilesMapper

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaFilesMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaFilesMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaFiles"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="company_id" property="companyId" /> <!-- 字段与属性的映射规则 -->
        <result column="company_name" property="companyName" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="file_type" property="fileType" /> <!-- 字段与属性的映射规则 -->
        <result column="tags" property="tags" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
        <result column="timelength" property="timelength" /> <!-- 字段与属性的映射规则 -->
        <result column="username" property="username" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="change_date" property="changeDate" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="remark" property="remark" /> <!-- 字段与属性的映射规则 -->
        <result column="audit_status" property="auditStatus" /> <!-- 字段与属性的映射规则 -->
        <result column="audit_mind" property="auditMind" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, company_id, company_name, filename, file_type, tags, bucket, file_id, url, timelength, username, create_date, change_date, status, remark, audit_status, audit_mind <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaProcessHistoryMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaProcessHistory; // 导入 MediaProcessHistory 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaProcessHistoryMapper extends BaseMapper<MediaProcessHistory> { // 定义 interface MediaProcessHistoryMapper

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaProcessHistoryMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaProcessHistoryMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaProcessHistory"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="finish_date" property="finishDate" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, file_id, filename, bucket, status, create_date, finish_date, url <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaProcessMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import org.apache.ibatis.annotations.Param; // 导入 Param 类
import org.apache.ibatis.annotations.Select; // 导入 Select 类
import org.apache.ibatis.annotations.Update; // 导入 Update 类

import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaProcessMapper extends BaseMapper<MediaProcess> { // 定义 interface MediaProcessMapper

    @Select("select * from media_process t where  t.id % #{shardTotal} = #{shardIndex} and (t.status=1 or t.status=3) and t.fail_count<3 limit #{count}") // 使用注解 @Select("select * from media_process t where  t.id % #{shardTotal} = #{shardIndex} and (t.status=1 or t.status=3) and t.fail_count<3 limit #{count}")
    List<MediaProcess>  selectListByShardIndex(@Param("shardTotal") int shardTotal, @Param("shardIndex") int shardIndex, @Param("count") int count); // 执行语句

    /** // 保留原作者写的块注释
     * 开启一个任务 // 保留原作者写的块注释
     * @param id 任务id // 保留原作者写的块注释
     * @return 更新记录数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Update("update media_process m set m.status='4' where (m.status='1' or m.status='3') and m.fail_count<3 and m.id=#{id}") // 使用注解 @Update("update media_process m set m.status='4' where (m.status='1' or m.status='3') and m.fail_count<3 and m.id=#{id}")
    int startTask(@Param("id") long id); // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MediaProcessMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MediaProcessMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MediaProcess"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="file_id" property="fileId" /> <!-- 字段与属性的映射规则 -->
        <result column="filename" property="filename" /> <!-- 字段与属性的映射规则 -->
        <result column="bucket" property="bucket" /> <!-- 字段与属性的映射规则 -->
        <result column="status" property="status" /> <!-- 字段与属性的映射规则 -->
        <result column="create_date" property="createDate" /> <!-- 字段与属性的映射规则 -->
        <result column="finish_date" property="finishDate" /> <!-- 字段与属性的映射规则 -->
        <result column="url" property="url" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, file_id, filename, bucket, status, create_date, finish_date, url <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MqMessageHistoryMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MqMessageHistory; // 导入 MqMessageHistory 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MqMessageHistoryMapper extends BaseMapper<MqMessageHistory> { // 定义 interface MqMessageHistoryMapper

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MqMessageHistoryMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MqMessageHistoryMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MqMessageHistory"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="message_type" property="messageType" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key1" property="businessKey1" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key2" property="businessKey2" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key3" property="businessKey3" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_host" property="mqHost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_port" property="mqPort" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_virtualhost" property="mqVirtualhost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_queue" property="mqQueue" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_num" property="informNum" /> <!-- 字段与属性的映射规则 -->
        <result column="state" property="state" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_date" property="returnfailureDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnsuccess_date" property="returnsuccessDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_msg" property="returnfailureMsg" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_date" property="informDate" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, message_type, business_key1, business_key2, business_key3, mq_host, mq_port, mq_virtualhost, mq_queue, inform_num, state, returnfailure_date, returnsuccess_date, returnfailure_msg, inform_date <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MqMessageMapper.java

package com.xuecheng.media.mapper; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 BaseMapper 类
import com.xuecheng.media.model.po.MqMessage; // 导入 MqMessage 类

/** // 保留原作者写的块注释
 * <p> // 保留原作者写的块注释
 *  Mapper 接口 // 保留原作者写的块注释
 * </p> // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author itcast // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MqMessageMapper extends BaseMapper<MqMessage> { // 定义 interface MqMessageMapper

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapper/MqMessageMapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL 语句片段 -->
<mapper namespace="com.xuecheng.media.mapper.MqMessageMapper"> <!-- MyBatis 映射文件的根标签 -->

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.xuecheng.media.model.po.MqMessage"> <!-- 定义结果映射 -->
        <id column="id" property="id" /> <!-- 主键列的映射规则 -->
        <result column="message_type" property="messageType" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key1" property="businessKey1" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key2" property="businessKey2" /> <!-- 字段与属性的映射规则 -->
        <result column="business_key3" property="businessKey3" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_host" property="mqHost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_port" property="mqPort" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_virtualhost" property="mqVirtualhost" /> <!-- 字段与属性的映射规则 -->
        <result column="mq_queue" property="mqQueue" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_num" property="informNum" /> <!-- 字段与属性的映射规则 -->
        <result column="state" property="state" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_date" property="returnfailureDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnsuccess_date" property="returnsuccessDate" /> <!-- 字段与属性的映射规则 -->
        <result column="returnfailure_msg" property="returnfailureMsg" /> <!-- 字段与属性的映射规则 -->
        <result column="inform_date" property="informDate" /> <!-- 字段与属性的映射规则 -->
    </resultMap> <!-- 结束 resultMap 区块 -->

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List"> <!-- 声明可复用的 SQL 片段 -->
        id, message_type, business_key1, business_key2, business_key3, mq_host, mq_port, mq_virtualhost, mq_queue, inform_num, state, returnfailure_date, returnsuccess_date, returnfailure_msg, inform_date <!-- SQL 语句片段 -->
    </sql> <!-- 结束 SQL 片段 -->

</mapper> <!-- 结束 mapper 标签 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/impl/MediaFileProcessServiceImpl.java

package com.xuecheng.media.service.impl; // 声明类所在的包路径

import com.xuecheng.media.mapper.MediaFilesMapper; // 导入 MediaFilesMapper 类
import com.xuecheng.media.mapper.MediaProcessHistoryMapper; // 导入 MediaProcessHistoryMapper 类
import com.xuecheng.media.mapper.MediaProcessMapper; // 导入 MediaProcessMapper 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.model.po.MediaProcessHistory; // 导入 MediaProcessHistory 类
import com.xuecheng.media.service.MediaFileProcessService; // 导入 MediaFileProcessService 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.stereotype.Service; // 导入 Service 类

import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description MediaFileProcess接口实现 // 保留原作者写的块注释
 * @date 2023/2/19 10:44 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class MediaFileProcessServiceImpl implements MediaFileProcessService { // 定义 class MediaFileProcessServiceImpl
    @Autowired // 使用注解 @Autowired
    MediaProcessMapper mediaProcessMapper; // 执行语句
    @Autowired // 使用注解 @Autowired
    MediaProcessHistoryMapper mediaProcessHistoryMapper; // 执行语句
    @Autowired // 使用注解 @Autowired
    MediaFilesMapper mediaFilesMapper; // 执行语句

    @Override // 使用注解 @Override
    public List<MediaProcess> getMediaProcessList(int shardIndex, int shardTotal, int count) { // 定义方法 getMediaProcessList(...)
        List<MediaProcess> mediaProcesses = mediaProcessMapper.selectListByShardIndex(shardTotal, shardIndex, count); // 把 mediaProcessMapper.selectListByShardIndex(shardTotal, shardIndex, count) 赋值给 mediaProcesses
        return mediaProcesses; // 返回 mediaProcesses
    } // 代码块结束

    //实现如下 // 保留原作者写的行内注释
    public boolean startTask(long id) { // 定义方法 startTask(...)
        int result = mediaProcessMapper.startTask(id); // 把 mediaProcessMapper.startTask(id) 赋值给 result
        return result<=0?false:true; // 返回 result<=0?false:true
    } // 代码块结束

    @Override // 使用注解 @Override
    public void saveProcessFinishStatus(Long taskId, String status, String fileId, String url, String errorMsg) { // 定义方法 saveProcessFinishStatus(...)

        //要更新的任务 // 保留原作者写的行内注释
        MediaProcess mediaProcess = mediaProcessMapper.selectById(taskId); // 把 mediaProcessMapper.selectById(taskId) 赋值给 mediaProcess
        if(mediaProcess == null){ // 定义方法 方法(...)
            return ; // 返回 
        } // 代码块结束
        //如果任务执行失败 // 保留原作者写的行内注释
        if(status.equals("3")){ // 定义方法 方法(...)
            //更新MediaProcess表的状态 // 保留原作者写的行内注释
            mediaProcess.setStatus("3"); // 执行语句
            mediaProcess.setFailCount(mediaProcess.getFailCount()+1);//失败次数加1 // 执行语句
            mediaProcess.setErrormsg(errorMsg); // 执行语句
            mediaProcessMapper.updateById(mediaProcess); // 执行语句
            //更高效的更新方式 // 保留原作者写的行内注释
//            mediaProcessMapper.update() // 保留原作者写的行内注释
            //todo:将上边的更新方式更改为效的更新方式 // 保留原作者写的行内注释
            return; // 直接返回不带结果

        } // 代码块结束


        //======如果任务执行成功====== // 保留原作者写的行内注释
        //文件表记录 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileId); // 把 mediaFilesMapper.selectById(fileId) 赋值给 mediaFiles
        //更新media_file表中的url // 保留原作者写的行内注释
        mediaFiles.setUrl(url); // 执行语句
        mediaFilesMapper.updateById(mediaFiles); // 执行语句

        //更新MediaProcess表的状态 // 保留原作者写的行内注释
        mediaProcess.setStatus("2"); // 执行语句
        mediaProcess.setFinishDate(LocalDateTime.now()); // 执行语句
        mediaProcess.setUrl(url); // 执行语句
        mediaProcessMapper.updateById(mediaProcess); // 执行语句

        //将MediaProcess表记录插入到MediaProcessHistory表 // 保留原作者写的行内注释
        MediaProcessHistory mediaProcessHistory = new MediaProcessHistory(); // 创建 MediaProcessHistory 对象并赋值给 mediaProcessHistory
        BeanUtils.copyProperties(mediaProcess,mediaProcessHistory); // 执行语句
        mediaProcessHistoryMapper.insert(mediaProcessHistory); // 执行语句

        //从MediaProcess删除当前任务 // 保留原作者写的行内注释
        mediaProcessMapper.deleteById(taskId); // 执行语句


    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/impl/MediaFileServiceImpl.java

package com.xuecheng.media.service.impl; // 声明类所在的包路径

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 导入 LambdaQueryWrapper 类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 Page 类
import com.j256.simplemagic.ContentInfo; // 导入 ContentInfo 类
import com.j256.simplemagic.ContentInfoUtil; // 导入 ContentInfoUtil 类
import com.xuecheng.base.exception.XueChengPlusException; // 导入 XueChengPlusException 类
import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.mapper.MediaFilesMapper; // 导入 MediaFilesMapper 类
import com.xuecheng.media.mapper.MediaProcessMapper; // 导入 MediaProcessMapper 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import io.minio.*; // 导入 * 类
import io.minio.errors.*; // 导入 * 类
import io.minio.messages.DeleteError; // 导入 DeleteError 类
import io.minio.messages.DeleteObject; // 导入 DeleteObject 类
import io.minio.messages.DeletedObject; // 导入 DeletedObject 类
import io.minio.messages.Item; // 导入 Item 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.apache.commons.codec.digest.DigestUtils; // 导入 DigestUtils 类
import org.apache.commons.io.IOUtils; // 导入 IOUtils 类
import org.apache.commons.lang3.StringUtils; // 导入 StringUtils 类
import org.springframework.beans.BeanUtils; // 导入 BeanUtils 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.http.MediaType; // 导入 MediaType 类
import org.springframework.stereotype.Service; // 导入 Service 类
import org.springframework.transaction.annotation.Transactional; // 导入 Transactional 类

import java.io.*; // 导入 * 类
import java.security.InvalidKeyException; // 导入 InvalidKeyException 类
import java.security.NoSuchAlgorithmException; // 导入 NoSuchAlgorithmException 类
import java.text.SimpleDateFormat; // 导入 SimpleDateFormat 类
import java.time.LocalDateTime; // 导入 LocalDateTime 类
import java.util.Date; // 导入 Date 类
import java.util.List; // 导入 List 类
import java.util.stream.Collectors; // 导入 Collectors 类
import java.util.stream.Stream; // 导入 Stream 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description TODO // 保留原作者写的块注释
 * @date 2022/9/10 8:58 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Service // 使用注解 @Service
public class MediaFileServiceImpl implements MediaFileService { // 定义 class MediaFileServiceImpl

    @Autowired // 使用注解 @Autowired
    MediaFilesMapper mediaFilesMapper; // 执行语句

    @Autowired // 使用注解 @Autowired
    MinioClient minioClient; // 执行语句

    // // 保留原作者写的行内注释
    @Autowired // 使用注解 @Autowired
    MediaFileService currentProxy; // 执行语句

    @Autowired // 使用注解 @Autowired
    MediaProcessMapper mediaProcessMapper; // 执行语句

    //存储普通文件 // 保留原作者写的行内注释
    @Value("${minio.bucket.files}") // 使用注解 @Value("${minio.bucket.files}")
    private String bucket_mediafiles; // 执行语句

    //存储视频 // 保留原作者写的行内注释
    @Value("${minio.bucket.videofiles}") // 使用注解 @Value("${minio.bucket.videofiles}")
    private String bucket_video; // 执行语句

    @Override // 使用注解 @Override
    public MediaFiles getFileById(String mediaId) { // 定义方法 getFileById(...)
        MediaFiles mediaFiles = mediaFilesMapper.selectById(mediaId); // 把 mediaFilesMapper.selectById(mediaId) 赋值给 mediaFiles
        return mediaFiles; // 返回 mediaFiles
    } // 代码块结束

    @Override // 使用注解 @Override
    public PageResult<MediaFiles> queryMediaFiels(Long companyId, PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto) { // 定义方法 queryMediaFiels(...)

        //构建查询条件对象 // 保留原作者写的行内注释
        LambdaQueryWrapper<MediaFiles> queryWrapper = new LambdaQueryWrapper<>(); // 创建 LambdaQueryWrapper<> 对象并赋值给 queryWrapper

        //分页对象 // 保留原作者写的行内注释
        Page<MediaFiles> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize()); // 创建 Page<> 对象并赋值给 page
        // 查询数据内容获得结果 // 保留原作者写的行内注释
        Page<MediaFiles> pageResult = mediaFilesMapper.selectPage(page, queryWrapper); // 把 mediaFilesMapper.selectPage(page, queryWrapper) 赋值给 pageResult
        // 获取数据列表 // 保留原作者写的行内注释
        // getRecords系统只带 // 保留原作者写的行内注释
        List<MediaFiles> list = pageResult.getRecords(); // 把 pageResult.getRecords() 的返回值赋给 list
        // 获取数据总数 // 保留原作者写的行内注释
        // getTotal系统自带 // 保留原作者写的行内注释
        long total = pageResult.getTotal(); // 把 pageResult.getTotal() 的返回值赋给 total
        // 构建结果集 // 保留原作者写的行内注释
        PageResult<MediaFiles> mediaListResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize()); // 创建 PageResult<> 对象并赋值给 mediaListResult
        return mediaListResult; // 返回 mediaListResult

    } // 代码块结束

    //根据文件扩展名(例如 .mp4)获取mimeType(该文件的MIME) // 保留原作者写的行内注释
    // MIME每个文件或数据块都可以用一个MIME类型字符串来描述自己的格式 // 保留原作者写的行内注释
    private String getMimeType(String extension){ // 定义方法 getMimeType(...)
        // 如果拿不到文件扩展名,于是把它看成空串,避免后续工具遇到null报错 // 保留原作者写的行内注释
        if(extension == null){ // 定义方法 方法(...)
            extension = ""; // 把 "" 赋值给 extension
        } // 代码块结束
        //根据扩展名取出mimeType // 保留原作者写的行内注释
        // ContentInfo用来描述文件识别的效果 // 保留原作者写的行内注释
        //findExtensionMatch根据文件扩展名返回,里面保护焊该类型的MIME类型,匹配度,文件描述等信息 // 保留原作者写的行内注释
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension); // 把 ContentInfoUtil.findExtensionMatch(extension) 赋值给 extensionMatch
        // MediaType是Spring框架提供的一个类型 // 保留原作者写的行内注释
        // 防止没有拿到文件扩展名,当无法判断文件的具体类型时,用这个告诉客户端,这是原始字节流,你按下载即可 // 保留原作者写的行内注释
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE; // 把 MediaType.APPLICATION_OCTET_STREAM_VALUE 赋值给 mimeType
        //通用mimeType,字节流 // 保留原作者写的行内注释
        if(extensionMatch!=null){ // 定义方法 方法(...)
            // getMimeType负责吧文件扩展名转换成标准MIME类型字符串 // 保留原作者写的行内注释
            // mimeType这个文件是什么类型 // 保留原作者写的行内注释
            mimeType = extensionMatch.getMimeType(); // 把 extensionMatch.getMimeType() 的返回值赋给 mimeType
        } // 代码块结束
        return mimeType; // 返回 mimeType

    } // 代码块结束

    /** // 保留原作者写的块注释
     * 将文件上传到minio // 保留原作者写的块注释
     * @param localFilePath 文件本地路径 // 保留原作者写的块注释
     * @param mimeType 媒体类型 // 保留原作者写的块注释
     * @param bucket 桶 // 保留原作者写的块注释
     * @param objectName 对象名 // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName){ // 定义方法 addMediaFilesToMinIO(...)
        try { // 尝试执行可能抛出异常的代码
            // Upload // 保留原作者写的行内注释
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder() // 代码逻辑
                    .bucket(bucket)//桶 // 代码逻辑
                    .filename(localFilePath) //指定本地文件路径 // 代码逻辑
                    .object(objectName)//对象名 放在子目录下 // 代码逻辑
                    .contentType(mimeType)//设置媒体文件类型 // 代码逻辑
                    .build(); // 执行语句
            //上传文件 // 保留原作者写的行内注释
            minioClient.uploadObject(uploadObjectArgs); // 执行语句
            log.debug("上传文件到minio成功,bucket:{},objectName:{},错误信息:{}",bucket,objectName); // 执行语句
            return true; // 返回 true
        } catch (Exception e) { // 定义方法 catch(...)
           e.printStackTrace(); // 执行语句
           log.error("上传文件出错,bucket:{},objectName:{},错误信息:{}",bucket,objectName,e.getMessage()); // 执行语句
        } // 代码块结束
        return false; // 返回 false
    } // 代码块结束

    //获取文件默认存储目录路径 年/月/日 // 保留原作者写的行内注释
    private String getDefaultFolderPath() { // 定义方法 getDefaultFolderPath(...)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 创建 SimpleDateFormat 对象并赋值给 sdf
        String folder = sdf.format(new Date()).replace("-", "/")+"/"; // 把 sdf.format(new Date()).replace("-", "/")+"/" 赋值给 folder
        return folder; // 返回 folder
    } // 代码块结束
    //获取文件的md5 // 保留原作者写的行内注释
    private String getFileMd5(File file) { // 定义方法 getFileMd5(...)
        try (FileInputStream fileInputStream = new FileInputStream(file)) { // 定义方法 FileInputStream(...)
            String fileMd5 = DigestUtils.md5Hex(fileInputStream); // 把 DigestUtils.md5Hex(fileInputStream) 赋值给 fileMd5
            return fileMd5; // 返回 fileMd5
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
            return null; // 返回 null
        } // 代码块结束
    } // 代码块结束

    @Override // 使用注解 @Override
    public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath,String objectName) { // 定义方法 uploadFile(...)

        //文件名 // 保留原作者写的行内注释
        String filename = uploadFileParamsDto.getFilename(); // 把 uploadFileParamsDto.getFilename() 的返回值赋给 filename
        //先得到扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension

        //得到mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(extension); // 把 getMimeType(extension) 赋值给 mimeType

        //子目录 // 保留原作者写的行内注释
        String defaultFolderPath = getDefaultFolderPath(); // 把 getDefaultFolderPath() 的返回值赋给 defaultFolderPath
        //文件的md5值 // 保留原作者写的行内注释
        String fileMd5 = getFileMd5(new File(localFilePath)); // 把 getFileMd5(new File(localFilePath)) 赋值给 fileMd5
        if(StringUtils.isEmpty(objectName)){ // 定义方法 方法(...)
            //使用默认年月日去存储 // 保留原作者写的行内注释
            objectName = defaultFolderPath+fileMd5+extension; // 把 defaultFolderPath+fileMd5+extension 赋值给 objectName
        } // 代码块结束
        //上传文件到minio // 保留原作者写的行内注释
        boolean result = addMediaFilesToMinIO(localFilePath, mimeType, bucket_mediafiles, objectName); // 把 addMediaFilesToMinIO(localFilePath, mimeType, bucket_mediafiles, objectName) 赋值给 result
        if(!result){ // 定义方法 方法(...)
            XueChengPlusException.cast("上传文件失败"); // 执行语句
        } // 代码块结束
        //入库文件信息 // 保留原作者写的行内注释
        MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName); // 把 currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName) 赋值给 mediaFiles
        if(mediaFiles==null){ // 定义方法 方法(...)
            XueChengPlusException.cast("文件上传后保存信息失败"); // 执行语句
        } // 代码块结束
        //准备返回的对象 // 保留原作者写的行内注释
        UploadFileResultDto uploadFileResultDto = new UploadFileResultDto(); // 创建 UploadFileResultDto 对象并赋值给 uploadFileResultDto
        BeanUtils.copyProperties(mediaFiles,uploadFileResultDto); // 执行语句

        return uploadFileResultDto; // 返回 uploadFileResultDto
    } // 代码块结束


    /** // 保留原作者写的块注释
     * @description 将文件信息添加到文件表 // 保留原作者写的块注释
     * @param companyId  机构id // 保留原作者写的块注释
     * @param fileMd5  文件md5值 // 保留原作者写的块注释
     * @param uploadFileParamsDto  上传文件的信息 // 保留原作者写的块注释
     * @param bucket  桶 // 保留原作者写的块注释
     * @param objectName 对象名称 // 保留原作者写的块注释
     * @return com.xuecheng.media.model.po.MediaFiles // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/12 21:22 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @Transactional // 使用注解 @Transactional
    public MediaFiles addMediaFilesToDb(Long companyId,String fileMd5,UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName){ // 定义方法 addMediaFilesToDb(...)
        //将文件信息保存到数据库 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5); // 把 mediaFilesMapper.selectById(fileMd5) 赋值给 mediaFiles
        if(mediaFiles == null){ // 定义方法 方法(...)
            mediaFiles = new MediaFiles(); // 创建 MediaFiles 对象并赋值给 mediaFiles
            BeanUtils.copyProperties(uploadFileParamsDto,mediaFiles); // 执行语句
            //文件id // 保留原作者写的行内注释
            mediaFiles.setId(fileMd5); // 执行语句
            //机构id // 保留原作者写的行内注释
            mediaFiles.setCompanyId(companyId); // 执行语句
            //桶 // 保留原作者写的行内注释
            mediaFiles.setBucket(bucket); // 执行语句
            //file_path // 保留原作者写的行内注释
            mediaFiles.setFilePath(objectName); // 执行语句
            //file_id // 保留原作者写的行内注释
            mediaFiles.setFileId(fileMd5); // 执行语句
            //url // 保留原作者写的行内注释
            mediaFiles.setUrl("/"+bucket+"/"+objectName); // 执行语句
            //上传时间 // 保留原作者写的行内注释
            mediaFiles.setCreateDate(LocalDateTime.now()); // 执行语句
            //状态 // 保留原作者写的行内注释
            mediaFiles.setStatus("1"); // 执行语句
            //审核状态 // 保留原作者写的行内注释
            mediaFiles.setAuditStatus("002003"); // 执行语句
            //插入数据库 // 保留原作者写的行内注释
            int insert = mediaFilesMapper.insert(mediaFiles); // 把 mediaFilesMapper.insert(mediaFiles) 赋值给 insert
            if(insert<=0){ // 定义方法 方法(...)
                log.debug("向数据库保存文件失败,bucket:{},objectName:{}",bucket,objectName); // 执行语句
                return null; // 返回 null
            } // 代码块结束
            //记录待处理任务 // 保留原作者写的行内注释
            addWaitingTask(mediaFiles); // 执行语句

            return mediaFiles; // 返回 mediaFiles

        } // 代码块结束
        return mediaFiles; // 返回 mediaFiles

    } // 代码块结束


    /** // 保留原作者写的块注释
     * 添加待处理任务 // 保留原作者写的块注释
     * @param mediaFiles 媒资文件信息 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private void addWaitingTask(MediaFiles mediaFiles){ // 定义方法 addWaitingTask(...)

        //文件名称 // 保留原作者写的行内注释
        String filename = mediaFiles.getFilename(); // 把 mediaFiles.getFilename() 的返回值赋给 filename
        //文件扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension
        //获取文件的 mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(extension); // 把 getMimeType(extension) 赋值给 mimeType
        if(mimeType.equals("video/x-msvideo")){//如果是avi视频写入待处理任务 // 定义方法 方法(...)
            MediaProcess mediaProcess = new MediaProcess(); // 创建 MediaProcess 对象并赋值给 mediaProcess
            BeanUtils.copyProperties(mediaFiles,mediaProcess); // 执行语句
            //状态是未处理 // 保留原作者写的行内注释
            mediaProcess.setStatus("1"); // 执行语句
            mediaProcess.setCreateDate(LocalDateTime.now()); // 执行语句
            mediaProcess.setFailCount(0);//失败次数默认0 // 执行语句
            mediaProcess.setUrl(null); // 执行语句
            mediaProcessMapper.insert(mediaProcess); // 执行语句

        } // 代码块结束

    } // 代码块结束


    @Override // 使用注解 @Override
    public RestResponse<Boolean> checkFile(String fileMd5) { // 定义方法 checkFile(...)
        //先查询数据库 // 保留原作者写的行内注释
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5); // 把 mediaFilesMapper.selectById(fileMd5) 赋值给 mediaFiles
        if(mediaFiles!=null){ // 定义方法 方法(...)
            //桶 // 保留原作者写的行内注释
            String bucket = mediaFiles.getBucket(); // 把 mediaFiles.getBucket() 的返回值赋给 bucket
            //objectname // 保留原作者写的行内注释
            String filePath = mediaFiles.getFilePath(); // 把 mediaFiles.getFilePath() 的返回值赋给 filePath
            //如果数据库存在再查询 minio // 保留原作者写的行内注释
            GetObjectArgs getObjectArgs = GetObjectArgs.builder() // 代码逻辑
                    .bucket(bucket) // 代码逻辑
                    .object(filePath) // 代码逻辑
                    .build(); // 执行语句
            //查询远程服务获取到一个流对象 // 保留原作者写的行内注释
            try { // 尝试执行可能抛出异常的代码
                FilterInputStream inputStream = minioClient.getObject(getObjectArgs); // 把 minioClient.getObject(getObjectArgs) 赋值给 inputStream
                if(inputStream!=null){ // 定义方法 方法(...)
                    //文件已存在 // 保留原作者写的行内注释
                    return RestResponse.success(true); // 返回 RestResponse.success(true)
                } // 代码块结束
            } catch (Exception e) { // 定义方法 catch(...)
                e.printStackTrace(); // 执行语句
            } // 代码块结束

        } // 代码块结束

        //文件不存在 // 保留原作者写的行内注释
        return RestResponse.success(false); // 返回 RestResponse.success(false)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex) { // 定义方法 checkChunk(...)

        //根据md5得到分块文件所在目录的路径 // 保留原作者写的行内注释
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5); // 把 getChunkFileFolderPath(fileMd5) 赋值给 chunkFileFolderPath

        //如果数据库存在再查询 minio // 保留原作者写的行内注释
        GetObjectArgs getObjectArgs = GetObjectArgs.builder() // 代码逻辑
                .bucket(bucket_video) // 代码逻辑
                .object(chunkFileFolderPath+chunkIndex) // 代码逻辑
                .build(); // 执行语句
        //查询远程服务获取到一个流对象 // 保留原作者写的行内注释
        try { // 尝试执行可能抛出异常的代码
            FilterInputStream inputStream = minioClient.getObject(getObjectArgs); // 把 minioClient.getObject(getObjectArgs) 赋值给 inputStream
            if(inputStream!=null){ // 定义方法 方法(...)
                //文件已存在 // 保留原作者写的行内注释
                return RestResponse.success(true); // 返回 RestResponse.success(true)
            } // 代码块结束
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
        } // 代码块结束

        //文件不存在 // 保留原作者写的行内注释
        return RestResponse.success(false); // 返回 RestResponse.success(false)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse uploadChunk(String fileMd5, int chunk, String localChunkFilePath) { // 定义方法 uploadChunk(...)
        //分块文件的路径 // 保留原作者写的行内注释
        String chunkFilePath = getChunkFileFolderPath(fileMd5) + chunk; // 把 getChunkFileFolderPath(fileMd5) + chunk 赋值给 chunkFilePath
        //获取mimeType // 保留原作者写的行内注释
        String mimeType = getMimeType(null); // 把 getMimeType(null) 赋值给 mimeType
        //将分块文件上传到minio // 保留原作者写的行内注释
        boolean b = addMediaFilesToMinIO(localChunkFilePath, mimeType, bucket_video, chunkFilePath); // 把 addMediaFilesToMinIO(localChunkFilePath, mimeType, bucket_video, chunkFilePath) 赋值给 b
        if(!b){ // 定义方法 方法(...)
            return RestResponse.validfail(false,"上传分块文件失败"); // 返回 RestResponse.validfail(false,"上传分块文件失败")
        } // 代码块结束
        //上传成功 // 保留原作者写的行内注释
        return RestResponse.success(true); // 返回 RestResponse.success(true)
    } // 代码块结束

    @Override // 使用注解 @Override
    public RestResponse mergechunks(Long companyId, String fileMd5, int chunkTotal, UploadFileParamsDto uploadFileParamsDto) { // 定义方法 mergechunks(...)
        //分块文件所在目录 // 保留原作者写的行内注释
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5); // 把 getChunkFileFolderPath(fileMd5) 赋值给 chunkFileFolderPath
        //找到所有的分块文件 // 保留原作者写的行内注释
        List<ComposeSource> sources = Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> ComposeSource.builder().bucket(bucket_video).object(chunkFileFolderPath + i).build()).collect(Collectors.toList()); // 把 Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> ComposeSource.builder().bucket(bucket_video).object(chunkFileFolderPath + i).build()).collect(Collectors.toList()) 赋值给 sources
        //源文件名称 // 保留原作者写的行内注释
        String filename = uploadFileParamsDto.getFilename(); // 把 uploadFileParamsDto.getFilename() 的返回值赋给 filename
        //扩展名 // 保留原作者写的行内注释
        String extension = filename.substring(filename.lastIndexOf(".")); // 把 filename.substring(filename.lastIndexOf(".")) 赋值给 extension
        //合并后文件的objectname // 保留原作者写的行内注释
        String objectName = getFilePathByMd5(fileMd5, extension); // 把 getFilePathByMd5(fileMd5, extension) 赋值给 objectName
        //指定合并后的objectName等信息 // 保留原作者写的行内注释
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder() // 代码逻辑
                .bucket(bucket_video) // 代码逻辑
                .object(objectName)//合并后的文件的objectname // 代码逻辑
                .sources(sources)//指定源文件 // 代码逻辑
                .build(); // 执行语句
        //===========合并文件============ // 保留原作者写的行内注释
        //报错size 1048576 must be greater than 5242880,minio默认的分块文件大小为5M // 保留原作者写的行内注释
        try { // 尝试执行可能抛出异常的代码
            minioClient.composeObject(composeObjectArgs); // 执行语句
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
            log.error("合并文件出错,bucket:{},objectName:{},错误信息:{}",bucket_video,objectName,e.getMessage()); // 执行语句
            return RestResponse.validfail(false,"合并文件异常"); // 返回 RestResponse.validfail(false,"合并文件异常")
        } // 代码块结束

        //===========校验合并后的和源文件是否一致,视频上传才成功=========== // 保留原作者写的行内注释
        //先下载合并后的文件 // 保留原作者写的行内注释
        File file = downloadFileFromMinIO(bucket_video, objectName); // 把 downloadFileFromMinIO(bucket_video, objectName) 赋值给 file
        try(FileInputStream fileInputStream = new FileInputStream(file)){ // 定义方法 FileInputStream(...)
            //计算合并后文件的md5 // 保留原作者写的行内注释
            String mergeFile_md5 = DigestUtils.md5Hex(fileInputStream); // 把 DigestUtils.md5Hex(fileInputStream) 赋值给 mergeFile_md5
            //比较原始md5和合并后文件的md5 // 保留原作者写的行内注释
            if(!fileMd5.equals(mergeFile_md5)){ // 定义方法 方法(...)
                log.error("校验合并文件md5值不一致,原始文件:{},合并文件:{}",fileMd5,mergeFile_md5); // 执行语句
                return RestResponse.validfail(false,"文件校验失败"); // 返回 RestResponse.validfail(false,"文件校验失败")
            } // 代码块结束
            //文件大小 // 保留原作者写的行内注释
            uploadFileParamsDto.setFileSize(file.length()); // 执行语句
        }catch (Exception e) { // 定义方法 方法(...)
            return RestResponse.validfail(false,"文件校验失败"); // 返回 RestResponse.validfail(false,"文件校验失败")
        } // 代码块结束

        //==============将文件信息入库============ // 保留原作者写的行内注释
        MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_video, objectName); // 把 currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_video, objectName) 赋值给 mediaFiles
        if(mediaFiles == null){ // 定义方法 方法(...)
            return RestResponse.validfail(false,"文件入库失败"); // 返回 RestResponse.validfail(false,"文件入库失败")
        } // 代码块结束
        //==========清理分块文件========= // 保留原作者写的行内注释
        clearChunkFiles(chunkFileFolderPath,chunkTotal); // 执行语句


        return RestResponse.success(true); // 返回 RestResponse.success(true)
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 清除分块文件 // 保留原作者写的块注释
     * @param chunkFileFolderPath 分块文件路径 // 保留原作者写的块注释
     * @param chunkTotal 分块文件总数 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private void clearChunkFiles(String chunkFileFolderPath,int chunkTotal){ // 定义方法 clearChunkFiles(...)
        Iterable<DeleteObject> objects =  Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> new DeleteObject(chunkFileFolderPath+ i)).collect(Collectors.toList());; // 把 Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> new DeleteObject(chunkFileFolderPath+ i)).collect(Collectors.toList()); 赋值给 objects
        RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucket_video).objects(objects).build(); // 把 RemoveObjectsArgs.builder().bucket(bucket_video).objects(objects).build() 的返回值赋给 removeObjectsArgs
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs); // 把 minioClient.removeObjects(removeObjectsArgs) 赋值给 results
        //要想真正删除 // 保留原作者写的行内注释
        results.forEach(f->{ // 定义方法 方法(...)
            try { // 尝试执行可能抛出异常的代码
                DeleteError deleteError = f.get(); // 把 f.get() 的返回值赋给 deleteError
            } catch (Exception e) { // 定义方法 catch(...)
                e.printStackTrace(); // 执行语句
            } // 代码块结束
        }); // 执行语句

    } // 代码块结束
    /** // 保留原作者写的块注释
     * 从minio下载文件 // 保留原作者写的块注释
     * @param bucket 桶 // 保留原作者写的块注释
     * @param objectName 对象名称 // 保留原作者写的块注释
     * @return 下载后的文件 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public File downloadFileFromMinIO(String bucket,String objectName){ // 定义方法 downloadFileFromMinIO(...)
        //临时文件 // 保留原作者写的行内注释
        File minioFile = null; // 把变量 minioFile 初始化为 null
        FileOutputStream outputStream = null; // 把变量 outputStream 初始化为 null
        try{ // 尝试执行可能抛出异常的代码
            InputStream stream = minioClient.getObject(GetObjectArgs.builder() // 代码逻辑
                    .bucket(bucket) // 代码逻辑
                    .object(objectName) // 代码逻辑
                    .build()); // 执行语句
            //创建临时文件 // 保留原作者写的行内注释
            minioFile=File.createTempFile("minio", ".merge"); // 把 File.createTempFile("minio", ".merge") 赋值给 minioFile
            outputStream = new FileOutputStream(minioFile); // 创建 FileOutputStream 对象并赋值给 outputStream
            IOUtils.copy(stream,outputStream); // 执行语句
            return minioFile; // 返回 minioFile
        } catch (Exception e) { // 定义方法 catch(...)
            e.printStackTrace(); // 执行语句
        }finally { // 代码逻辑
            if(outputStream!=null){ // 定义方法 方法(...)
                try { // 尝试执行可能抛出异常的代码
                    outputStream.close(); // 执行语句
                } catch (IOException e) { // 定义方法 catch(...)
                    e.printStackTrace(); // 执行语句
                } // 代码块结束
            } // 代码块结束
        } // 代码块结束
        return null; // 返回 null
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 得到合并后的文件的地址 // 保留原作者写的块注释
     * @param fileMd5 文件id即md5值 // 保留原作者写的块注释
     * @param fileExt 文件扩展名 // 保留原作者写的块注释
     * @return // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    private String getFilePathByMd5(String fileMd5,String fileExt){ // 定义方法 getFilePathByMd5(...)
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt; // 返回   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt
    } // 代码块结束

    //得到分块文件的目录 // 保留原作者写的行内注释
    private String getChunkFileFolderPath(String fileMd5) { // 定义方法 getChunkFileFolderPath(...)
        return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + "chunk" + "/"; // 返回 fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + "chunk" + "/"
    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/jobhandler/SampleXxlJob.java

package com.xuecheng.media.service.jobhandler; // 声明类所在的包路径

import com.xxl.job.core.context.XxlJobHelper; // 导入 XxlJobHelper 类
import com.xxl.job.core.handler.annotation.XxlJob; // 导入 XxlJob 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.io.BufferedInputStream; // 导入 BufferedInputStream 类
import java.io.BufferedReader; // 导入 BufferedReader 类
import java.io.DataOutputStream; // 导入 DataOutputStream 类
import java.io.InputStreamReader; // 导入 InputStreamReader 类
import java.net.HttpURLConnection; // 导入 HttpURLConnection 类
import java.net.URL; // 导入 URL 类
import java.util.Arrays; // 导入 Arrays 类
import java.util.concurrent.TimeUnit; // 导入 TimeUnit 类

/** // 保留原作者写的块注释
 * XxlJob开发示例(Bean模式) // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * 开发步骤: // 保留原作者写的块注释
 *      1、任务开发:在Spring Bean实例中,开发Job方法; // 保留原作者写的块注释
 *      2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。 // 保留原作者写的块注释
 *      3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志; // 保留原作者写的块注释
 *      4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果; // 保留原作者写的块注释
 * // 保留原作者写的块注释
 * @author xuxueli 2019-12-11 21:52:51 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Component // 使用注解 @Component
public class SampleXxlJob { // 定义 class SampleXxlJob
    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class); // 把 LoggerFactory.getLogger(SampleXxlJob.class) 赋值给 logger


    /** // 保留原作者写的块注释
     * 1、简单任务示例(Bean模式) // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("demoJobHandler") // 使用注解 @XxlJob("demoJobHandler")
    public void demoJobHandler() throws Exception { // 定义方法 demoJobHandler(...)
        System.out.println("处理视频......."); // 执行语句


    } // 代码块结束


    @XxlJob("demoJobHandler2") // 使用注解 @XxlJob("demoJobHandler2")
    public void demoJobHandler2() throws Exception { // 定义方法 demoJobHandler2(...)
        System.out.println("处理文档......."); // 执行语句

        // default success // 保留原作者写的行内注释
    } // 代码块结束

    /** // 保留原作者写的块注释
     * 2、分片广播任务 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("shardingJobHandler") // 使用注解 @XxlJob("shardingJobHandler")
    public void shardingJobHandler() throws Exception { // 定义方法 shardingJobHandler(...)

        // 分片参数 // 保留原作者写的行内注释
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号,从0开始 // 把 XxlJobHelper.getShardIndex() 的返回值赋给 shardIndex
        int shardTotal = XxlJobHelper.getShardTotal();//执行器总数 // 把 XxlJobHelper.getShardTotal() 的返回值赋给 shardTotal

        System.out.println("shardIndex="+shardIndex+",shardTotal="+shardTotal); // 把 "+shardIndex+",shardTotal="+shardTotal) 赋值给 System.out.println("shardIndex

    } // 代码块结束

} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/jobhandler/VideoTask.java

package com.xuecheng.media.service.jobhandler; // 声明类所在的包路径

import com.xuecheng.base.utils.Mp4VideoUtil; // 导入 Mp4VideoUtil 类
import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类
import com.xuecheng.media.service.MediaFileProcessService; // 导入 MediaFileProcessService 类
import com.xuecheng.media.service.MediaFileService; // 导入 MediaFileService 类
import com.xxl.job.core.context.XxlJobHelper; // 导入 XxlJobHelper 类
import com.xxl.job.core.handler.annotation.XxlJob; // 导入 XxlJob 类
import lombok.extern.slf4j.Slf4j; // 导入 Slf4j 类
import org.slf4j.Logger; // 导入 Logger 类
import org.slf4j.LoggerFactory; // 导入 LoggerFactory 类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 类
import org.springframework.beans.factory.annotation.Value; // 导入 Value 类
import org.springframework.stereotype.Component; // 导入 Component 类

import java.io.File; // 导入 File 类
import java.io.IOException; // 导入 IOException 类
import java.util.List; // 导入 List 类
import java.util.concurrent.*; // 导入 * 类

/** // 保留原作者写的块注释
 * 任务处理类 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
@Slf4j // 使用注解 @Slf4j
@Component // 使用注解 @Component
public class VideoTask { // 定义 class VideoTask

    @Autowired // 使用注解 @Autowired
    MediaFileProcessService mediaFileProcessService; // 执行语句

    @Autowired // 使用注解 @Autowired
    MediaFileService mediaFileService; // 执行语句

    //ffmpeg的路径 // 保留原作者写的行内注释
    @Value("${videoprocess.ffmpegpath}") // 使用注解 @Value("${videoprocess.ffmpegpath}")
    private String ffmpegpath; // 执行语句

    /** // 保留原作者写的块注释
     * 视频处理任务 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    @XxlJob("videoJobHandler") // 使用注解 @XxlJob("videoJobHandler")
    public void videoJobHandler() throws Exception { // 定义方法 videoJobHandler(...)

        // 分片参数 // 保留原作者写的行内注释
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号,从0开始 // 把 XxlJobHelper.getShardIndex() 的返回值赋给 shardIndex
        int shardTotal = XxlJobHelper.getShardTotal();//执行器总数 // 把 XxlJobHelper.getShardTotal() 的返回值赋给 shardTotal

        //确定cpu的核心数 // 保留原作者写的行内注释
        int processors = Runtime.getRuntime().availableProcessors(); // 把 Runtime.getRuntime().availableProcessors() 的返回值赋给 processors
        //查询待处理的任务 // 保留原作者写的行内注释
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, processors); // 把 mediaFileProcessService.getMediaProcessList(shardIndex, shardTotal, processors) 赋值给 mediaProcessList

        //任务数量 // 保留原作者写的行内注释
        int size = mediaProcessList.size(); // 把 mediaProcessList.size() 的返回值赋给 size
        log.debug("取到视频处理任务数:"+size); // 执行语句
        if(size<=0){ // 定义方法 方法(...)
            return; // 直接返回不带结果
        } // 代码块结束
        //创建一个线程池 // 保留原作者写的行内注释
        ExecutorService executorService = Executors.newFixedThreadPool(size); // 把 Executors.newFixedThreadPool(size) 赋值给 executorService
        //使用的计数器 // 保留原作者写的行内注释
        CountDownLatch countDownLatch = new CountDownLatch(size); // 创建 CountDownLatch 对象并赋值给 countDownLatch
        mediaProcessList.forEach(mediaProcess -> { // 定义方法 方法(...)
            //将任务加入线程池 // 保留原作者写的行内注释
            executorService.execute(()->{ // 定义方法 方法(...)
                try { // 尝试执行可能抛出异常的代码
                    //任务id // 保留原作者写的行内注释
                    Long taskId = mediaProcess.getId(); // 把 mediaProcess.getId() 的返回值赋给 taskId
                    //文件id就是md5 // 保留原作者写的行内注释
                    String fileId = mediaProcess.getFileId(); // 把 mediaProcess.getFileId() 的返回值赋给 fileId
                    //开启任务 // 保留原作者写的行内注释
                    boolean b = mediaFileProcessService.startTask(taskId); // 把 mediaFileProcessService.startTask(taskId) 赋值给 b
                    if (!b) { // 定义方法 方法(...)
                        log.debug("抢占任务失败,任务id:{}", taskId); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束

                    //桶 // 保留原作者写的行内注释
                    String bucket = mediaProcess.getBucket(); // 把 mediaProcess.getBucket() 的返回值赋给 bucket
                    //objectName // 保留原作者写的行内注释
                    String objectName = mediaProcess.getFilePath(); // 把 mediaProcess.getFilePath() 的返回值赋给 objectName

                    //下载minio视频到本地 // 保留原作者写的行内注释
                    File file = mediaFileService.downloadFileFromMinIO(bucket, objectName); // 把 mediaFileService.downloadFileFromMinIO(bucket, objectName) 赋值给 file
                    if (file == null) { // 定义方法 方法(...)
                        log.debug("下载视频出错,任务id:{},bucket:{},objectName:{}", taskId, bucket, objectName); // 执行语句
                        //保存任务处理失败的结果 // 保留原作者写的行内注释
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "下载视频到本地失败"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束

                    //源avi视频的路径 // 保留原作者写的行内注释
                    String video_path = file.getAbsolutePath(); // 把 file.getAbsolutePath() 的返回值赋给 video_path
                    //转换后mp4文件的名称 // 保留原作者写的行内注释
                    String mp4_name = fileId + ".mp4"; // 把 fileId + ".mp4" 赋值给 mp4_name
                    //转换后mp4文件的路径 // 保留原作者写的行内注释
                    //先创建一个临时文件,作为转换后的文件 // 保留原作者写的行内注释
                    File mp4File = null; // 把变量 mp4File 初始化为 null
                    try { // 尝试执行可能抛出异常的代码
                        mp4File = File.createTempFile("minio", ".mp4"); // 把 File.createTempFile("minio", ".mp4") 赋值给 mp4File
                    } catch (IOException e) { // 定义方法 catch(...)
                        log.debug("创建临时文件异常,{}", e.getMessage()); // 执行语句
                        //保存任务处理失败的结果 // 保留原作者写的行内注释
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "创建临时文件异常"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束
                    String mp4_path = mp4File.getAbsolutePath(); // 把 mp4File.getAbsolutePath() 的返回值赋给 mp4_path
                    //创建工具类对象 // 保留原作者写的行内注释
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath, video_path, mp4_name, mp4_path); // 创建 Mp4VideoUtil 对象并赋值给 videoUtil
                    //开始视频转换,成功将返回success,失败返回失败原因 // 保留原作者写的行内注释
                    String result = videoUtil.generateMp4(); // 把 videoUtil.generateMp4() 的返回值赋给 result
                    if (!result.equals("success")) { // 定义方法 方法(...)

                        log.debug("视频转码失败,原因:{},bucket:{},objectName:{},", result, bucket, objectName); // 执行语句
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, result); // 执行语句
                        return; // 直接返回不带结果

                    } // 代码块结束
                    //上传到minio // 保留原作者写的行内注释
                    boolean b1 = mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", bucket, objectName); // 把 mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", bucket, objectName) 赋值给 b1
                    if (!b1) { // 定义方法 方法(...)
                        log.debug("上传mp4到minio失败,taskid:{}", taskId); // 执行语句
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "上传mp4到minio失败"); // 执行语句
                        return; // 直接返回不带结果
                    } // 代码块结束
                    //mp4文件的url // 保留原作者写的行内注释
                    String url = getFilePath(fileId, ".mp4"); // 把 getFilePath(fileId, ".mp4") 赋值给 url

                    //更新任务状态为成功 // 保留原作者写的行内注释
                    mediaFileProcessService.saveProcessFinishStatus(taskId, "2", fileId, url, "创建临时文件异常"); // 执行语句
                }finally { // 代码逻辑
                    //计算器减去1 // 保留原作者写的行内注释
                    countDownLatch.countDown(); // 执行语句
                } // 代码块结束

            }); // 执行语句

        }); // 执行语句

        //阻塞,指定最大限制的等待时间,阻塞最多等待一定的时间后就解除阻塞 // 保留原作者写的行内注释
        countDownLatch.await(30, TimeUnit.MINUTES); // 执行语句


    } // 代码块结束

    private String getFilePath(String fileMd5,String fileExt){ // 定义方法 getFilePath(...)
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt; // 返回   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt
    } // 代码块结束
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/MediaFileProcessService.java

package com.xuecheng.media.service; // 声明类所在的包路径

import com.xuecheng.media.model.po.MediaProcess; // 导入 MediaProcess 类

import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 任务处理 // 保留原作者写的块注释
 * @date 2023/2/19 10:43 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFileProcessService { // 定义 interface MediaFileProcessService

    /** // 保留原作者写的块注释
     * @description 获取待处理任务 // 保留原作者写的块注释
     * @param shardIndex 分片序号 // 保留原作者写的块注释
     * @param shardTotal 分片总数 // 保留原作者写的块注释
     * @param count 获取记录数 // 保留原作者写的块注释
     * @return java.util.List<com.xuecheng.media.model.po.MediaProcess> // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/9/14 14:49 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public List<MediaProcess> getMediaProcessList(int shardIndex, int shardTotal, int count); // 执行语句

    /** // 保留原作者写的块注释
     *  开启一个任务 // 保留原作者写的块注释
     * @param id 任务id // 保留原作者写的块注释
     * @return true开启任务成功,false开启任务失败 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    public boolean startTask(long id); // 执行语句


    /** // 保留原作者写的块注释
     * @description 保存任务结果 // 保留原作者写的块注释
     * @param taskId  任务id // 保留原作者写的块注释
     * @param status 任务状态 // 保留原作者写的块注释
     * @param fileId  文件id // 保留原作者写的块注释
     * @param url url // 保留原作者写的块注释
     * @param errorMsg 错误信息 // 保留原作者写的块注释
     * @return void // 保留原作者写的块注释
     * @author Mr.M // 保留原作者写的块注释
     * @date 2022/10/15 11:29 // 保留原作者写的块注释
     */ // 保留原作者写的块注释
    void saveProcessFinishStatus(Long taskId,String status,String fileId,String url,String errorMsg); // 执行语句


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/MediaFileService.java

package com.xuecheng.media.service; // 声明类所在的包路径

import com.xuecheng.base.model.PageParams; // 导入 PageParams 类
import com.xuecheng.base.model.PageResult; // 导入 PageResult 类
import com.xuecheng.base.model.RestResponse; // 导入 RestResponse 类
import com.xuecheng.media.model.dto.QueryMediaParamsDto; // 导入 QueryMediaParamsDto 类
import com.xuecheng.media.model.dto.UploadFileParamsDto; // 导入 UploadFileParamsDto 类
import com.xuecheng.media.model.dto.UploadFileResultDto; // 导入 UploadFileResultDto 类
import com.xuecheng.media.model.po.MediaFiles; // 导入 MediaFiles 类
import io.minio.UploadObjectArgs; // 导入 UploadObjectArgs 类
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 类

import java.io.File; // 导入 File 类
import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @description 媒资文件管理业务类 // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @date 2022/9/10 8:55 // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public interface MediaFileService { // 定义 interface MediaFileService

 //根据媒资id查询文件信息 // 保留原作者写的行内注释
 MediaFiles getFileById(String mediaId); // 执行语句

 /** // 保留原作者写的块注释
  * @description 媒资文件查询方法 // 保留原作者写的块注释
  * @param pageParams 分页参数 // 保留原作者写的块注释
  * @param queryMediaParamsDto 查询条件 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.PageResult<com.xuecheng.media.model.po.MediaFiles> // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/10 8:57 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
 public PageResult<MediaFiles> queryMediaFiels(Long companyId,PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto); // 执行语句

 /** // 保留原作者写的块注释
  * 上传文件 // 保留原作者写的块注释
  * @param // 保留原作者写的块注释
  * companyId 机构id // 保留原作者写的块注释
  * @param uploadFileParamsDto 文件信息 // 保留原作者写的块注释
  * @param localFilePath 文件本地路径 // 保留原作者写的块注释
  * @param objectname 如果传入objectname要按objectname的目录去存储,如果不传就按年月日目录结构去存储 // 保留原作者写的块注释
  * @return UploadFileResultDto // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath,String objectname); // 执行语句

 public MediaFiles addMediaFilesToDb(Long companyId,String fileMd5,UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName); // 执行语句

 /** // 保留原作者写的块注释
  * 将文件上传到minio // 保留原作者写的块注释
  * @param localFilePath 文件本地路径 // 保留原作者写的块注释
  * @param mimeType 媒体类型 // 保留原作者写的块注释
  * @param bucket 桶 // 保留原作者写的块注释
  * @param objectName 对象名 // 保留原作者写的块注释
  * @return // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName); // 执行语句

 /** // 保留原作者写的块注释
  * @description 检查文件是否存在 // 保留原作者写的块注释
  * @param fileMd5 文件的md5 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse<java.lang.Boolean> false不存在,true存在 // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:38 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse<Boolean> checkFile(String fileMd5); // 执行语句

 /** // 保留原作者写的块注释
  * @description 检查分块是否存在 // 保留原作者写的块注释
  * @param fileMd5  文件的md5 // 保留原作者写的块注释
  * @param chunkIndex  分块序号 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse<java.lang.Boolean> false不存在,true存在 // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:39 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex); // 执行语句

 /** // 保留原作者写的块注释
  * @description 上传分块 // 保留原作者写的块注释
  * @param fileMd5  文件md5 // 保留原作者写的块注释
  * @param chunk  分块序号 // 保留原作者写的块注释
  * @param localChunkFilePath  分块文件本地路径 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:50 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse uploadChunk(String fileMd5,int chunk,String localChunkFilePath); // 执行语句


 /** // 保留原作者写的块注释
  * @description 合并分块 // 保留原作者写的块注释
  * @param companyId  机构id // 保留原作者写的块注释
  * @param fileMd5  文件md5 // 保留原作者写的块注释
  * @param chunkTotal 分块总和 // 保留原作者写的块注释
  * @param uploadFileParamsDto 文件信息 // 保留原作者写的块注释
  * @return com.xuecheng.base.model.RestResponse // 保留原作者写的块注释
  * @author Mr.M // 保留原作者写的块注释
  * @date 2022/9/13 15:56 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public RestResponse mergechunks(Long companyId,String fileMd5,int chunkTotal,UploadFileParamsDto uploadFileParamsDto); // 执行语句

 /** // 保留原作者写的块注释
  * 从minio下载文件 // 保留原作者写的块注释
  * @param bucket 桶 // 保留原作者写的块注释
  * @param objectName 对象名称 // 保留原作者写的块注释
  * @return 下载后的文件 // 保留原作者写的块注释
  */ // 保留原作者写的块注释
 public File downloadFileFromMinIO(String bucket, String objectName); // 执行语句
} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/resources/bootstrap.yml

spring:
  application:
    name: media-service
  cloud:
    nacos:
      server-addr: 192.168.101.65:8848
      discovery:
        namespace: dev402
        group: xuecheng-plus-project
      config:
        namespace: dev402
        group: xuecheng-plus-project
        file-extension: yaml
        refresh-enabled: true
      shared-configs:
        - data-id: logging-${spring.profiles.active}.yaml
          group: xuecheng-plus-common
          refresh: true

#profiles默认为dev
  profiles:
    active: dev




文件:xuecheng-plus-media/xuecheng-plus-media-service/src/main/resources/log4j2-dev.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明 -->
<Configuration monitorInterval="180" packages=""> <!-- SQL 语句片段 -->
    <properties> <!-- SQL 语句片段 -->
        <property name="logdir">logs</property> <!-- SQL 语句片段 -->
        <property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwable</property> <!-- SQL 语句片段 -->
    </properties> <!-- SQL 语句片段 -->
    <Appenders> <!-- SQL 语句片段 -->
        <Console name="Console" target="SYSTEM_OUT"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
        </Console> <!-- SQL 语句片段 -->

        <RollingFile name="ErrorAppender" fileName="${logdir}/error.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->

        <RollingFile name="DebugAppender" fileName="${logdir}/info.log" <!-- SQL 语句片段 -->
            filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true"> <!-- SQL 语句片段 -->
            <PatternLayout pattern="${PATTERN}"/> <!-- SQL 语句片段 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> <!-- SQL 语句片段 -->
            <Policies> <!-- SQL 语句片段 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- SQL 语句片段 -->
            </Policies> <!-- SQL 语句片段 -->
        </RollingFile> <!-- SQL 语句片段 -->
        
        <!--异步appender-->
         <Async name="AsyncAppender" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="ErrorAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Async> <!-- SQL 语句片段 -->
    </Appenders> <!-- SQL 语句片段 -->
    
    <Loggers> <!-- SQL 语句片段 -->
         <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="org.mybatis" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="springfox" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		<logger name="org.apache.http" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        <logger name="com.netflix.discovery" level="INFO"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
        
        <logger name="RocketmqCommon"  level="INFO" > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqRemoting" level="INFO"  > <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->
		
		<logger name="RocketmqClient" level="WARN"> <!-- SQL 语句片段 -->
		</logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.lottery" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->

        <logger name="org.dromara.hmily.bonuspoint" level="WARN"> <!-- SQL 语句片段 -->
        </logger> <!-- SQL 语句片段 -->
		
        <!--OFF   0-->
        <!--FATAL   100-->
        <!--ERROR   200-->
        <!--WARN   300-->
        <!--INFO   400-->
        <!--DEBUG   500-->
        <!--TRACE   600-->
        <!--ALL   Integer.MAX_VALUE-->
        <Root level="DEBUG" includeLocation="true"> <!-- SQL 语句片段 -->
            <AppenderRef ref="AsyncAppender"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="Console"/> <!-- SQL 语句片段 -->
            <AppenderRef ref="DebugAppender"/> <!-- SQL 语句片段 -->
        </Root> <!-- SQL 语句片段 -->
    </Loggers> <!-- SQL 语句片段 -->
</Configuration> <!-- SQL 语句片段 -->

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/test/java/com/xuecheng/media/BigFileTest.java

package com.xuecheng.media; // 声明类所在的包路径

import org.apache.commons.codec.digest.DigestUtils; // 导入 DigestUtils 类
import org.junit.jupiter.api.Test; // 导入 Test 类

import java.io.*; // 导入 * 类
import java.util.Arrays; // 导入 Arrays 类
import java.util.Collections; // 导入 Collections 类
import java.util.Comparator; // 导入 Comparator 类
import java.util.List; // 导入 List 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 测试大文件上传方法 // 保留原作者写的块注释
 * @date 2023/2/18 9:24 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public class BigFileTest { // 定义 class BigFileTest

    //分块测试 // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void testChunk() throws IOException { // 定义方法 testChunk(...)
        //源文件 // 保留原作者写的行内注释
        File sourceFile = new File("D:\\develop\\upload\\1.项目背景.mp4"); // 创建 File 对象并赋值给 sourceFile
        //分块文件存储路径 // 保留原作者写的行内注释
        String chunkFilePath = "D:\\develop\\upload\\chunk\\"; // 把 "D:\\develop\\upload\\chunk\\" 赋值给 chunkFilePath
        //分块文件大小 // 保留原作者写的行内注释
        int chunkSize = 1024 * 1024 * 5; // 把 1024 * 1024 * 5 赋值给 chunkSize
        //分块文件个数 // 保留原作者写的行内注释
        int chunkNum = (int) Math.ceil(sourceFile.length() * 1.0 / chunkSize); // 把 (int) Math.ceil(sourceFile.length() * 1.0 / chunkSize) 赋值给 chunkNum
        //使用流从源文件读数据,向分块文件中写数据 // 保留原作者写的行内注释
        RandomAccessFile raf_r = new RandomAccessFile(sourceFile, "r"); // 创建 RandomAccessFile 对象并赋值给 raf_r
        //缓存区 // 保留原作者写的行内注释
        byte[] bytes = new byte[1024]; // 创建 byte[1024] 对象并赋值给 bytes
        for (int i = 0; i < chunkNum; i++) { // 定义方法 方法(...)
            File chunkFile = new File(chunkFilePath + i); // 创建 File 对象并赋值给 chunkFile
            //分块文件写入流 // 保留原作者写的行内注释
            RandomAccessFile raf_rw = new RandomAccessFile(chunkFile, "rw"); // 创建 RandomAccessFile 对象并赋值给 raf_rw
            int len = -1; // 把 -1 赋值给 len
            while ((len=raf_r.read(bytes))!=-1){ // 定义方法 方法(...)
                raf_rw.write(bytes,0,len); // 执行语句
                if(chunkFile.length()>=chunkSize){ // 定义方法 方法(...)
                    break; // 跳出当前循环\u6216分支
                } // 代码块结束
            } // 代码块结束
            raf_rw.close(); // 执行语句
        } // 代码块结束
        raf_r.close(); // 执行语句

    } // 代码块结束

    //将分块进行合并 // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void testMerge() throws IOException { // 定义方法 testMerge(...)
        //块文件目录 // 保留原作者写的行内注释
        File chunkFolder = new File("D:\\develop\\upload\\chunk"); // 创建 File 对象并赋值给 chunkFolder
        //源文件 // 保留原作者写的行内注释
        File sourceFile = new File("D:\\develop\\upload\\1.项目背景.mp4"); // 创建 File 对象并赋值给 sourceFile
        //合并后的文件 // 保留原作者写的行内注释
        File mergeFile = new File("D:\\develop\\upload\\1.项目背景_2.mp4"); // 创建 File 对象并赋值给 mergeFile

        //取出所有分块文件 // 保留原作者写的行内注释
        File[] files = chunkFolder.listFiles(); // 把 chunkFolder.listFiles() 的返回值赋给 files
        //将数组转成list // 保留原作者写的行内注释
        List<File> filesList = Arrays.asList(files); // 把 Arrays.asList(files) 赋值给 filesList
        //对分块文件排序 // 保留原作者写的行内注释
        Collections.sort(filesList, new Comparator<File>() { // 定义方法 方法(...)
            @Override // 使用注解 @Override
            public int compare(File o1, File o2) { // 定义方法 compare(...)
                return Integer.parseInt(o1.getName())-Integer.parseInt(o2.getName()); // 返回 Integer.parseInt(o1.getName())-Integer.parseInt(o2.getName())
            } // 代码块结束
        }); // 执行语句
        //向合并文件写的流 // 保留原作者写的行内注释
        RandomAccessFile raf_rw = new RandomAccessFile(mergeFile, "rw"); // 创建 RandomAccessFile 对象并赋值给 raf_rw
        //缓存区 // 保留原作者写的行内注释
        byte[] bytes = new byte[1024]; // 创建 byte[1024] 对象并赋值给 bytes
        //遍历分块文件,向合并 的文件写 // 保留原作者写的行内注释
        for (File file : filesList) { // 定义方法 方法(...)
            //读分块的流 // 保留原作者写的行内注释
            RandomAccessFile raf_r = new RandomAccessFile(file, "r"); // 创建 RandomAccessFile 对象并赋值给 raf_r
            int len = -1; // 把 -1 赋值给 len
            while ((len=raf_r.read(bytes))!=-1){ // 定义方法 方法(...)
                raf_rw.write(bytes,0,len); // 执行语句
            } // 代码块结束
            raf_r.close(); // 执行语句

        } // 代码块结束
        raf_rw.close(); // 执行语句
        //合并文件完成后对合并的文件md5校验 // 保留原作者写的行内注释
        FileInputStream fileInputStream_merge = new FileInputStream(mergeFile); // 创建 FileInputStream 对象并赋值给 fileInputStream_merge
        FileInputStream fileInputStream_source = new FileInputStream(sourceFile); // 创建 FileInputStream 对象并赋值给 fileInputStream_source
        String md5_merge = DigestUtils.md5Hex(fileInputStream_merge); // 把 DigestUtils.md5Hex(fileInputStream_merge) 赋值给 md5_merge
        String md5_source = DigestUtils.md5Hex(fileInputStream_source); // 把 DigestUtils.md5Hex(fileInputStream_source) 赋值给 md5_source
        if(md5_merge.equals(md5_source)){ // 定义方法 方法(...)
            System.out.println("文件合并成功"); // 执行语句
        } // 代码块结束

    } // 代码块结束


} // 代码块结束

文件:xuecheng-plus-media/xuecheng-plus-media-service/src/test/java/com/xuecheng/media/MinioTest.java

package com.xuecheng.media; // 声明类所在的包路径

import com.j256.simplemagic.ContentInfo; // 导入 ContentInfo 类
import com.j256.simplemagic.ContentInfoUtil; // 导入 ContentInfoUtil 类
import io.minio.*; // 导入 * 类
import io.minio.errors.*; // 导入 * 类
import org.apache.commons.codec.digest.DigestUtils; // 导入 DigestUtils 类
import org.apache.commons.io.IOUtils; // 导入 IOUtils 类
import org.junit.jupiter.api.Test; // 导入 Test 类
import org.springframework.http.MediaType; // 导入 MediaType 类

import java.io.*; // 导入 * 类
import java.security.InvalidKeyException; // 导入 InvalidKeyException 类
import java.security.NoSuchAlgorithmException; // 导入 NoSuchAlgorithmException 类
import java.util.ArrayList; // 导入 ArrayList 类
import java.util.List; // 导入 List 类
import java.util.stream.Collectors; // 导入 Collectors 类
import java.util.stream.Stream; // 导入 Stream 类

/** // 保留原作者写的块注释
 * @author Mr.M // 保留原作者写的块注释
 * @version 1.0 // 保留原作者写的块注释
 * @description 测试minio的sdk // 保留原作者写的块注释
 * @date 2023/2/17 11:55 // 保留原作者写的块注释
 */ // 保留原作者写的块注释
public class MinioTest { // 定义 class MinioTest

    MinioClient minioClient = // 代码逻辑
            MinioClient.builder() // 代码逻辑
                    .endpoint("http://192.168.101.65:9000") // 代码逻辑
                    .credentials("minioadmin", "minioadmin") // 代码逻辑
                    .build(); // 执行语句

    @Test // 使用注解 @Test
    public void test_upload() throws Exception { // 定义方法 test_upload(...)

        //通过扩展名得到媒体资源类型 mimeType // 保留原作者写的行内注释
        //根据扩展名取出mimeType // 保留原作者写的行内注释
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4"); // 把 ContentInfoUtil.findExtensionMatch(".mp4") 赋值给 extensionMatch
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流 // 把 MediaType.APPLICATION_OCTET_STREAM_VALUE 赋值给 mimeType
        if(extensionMatch!=null){ // 定义方法 方法(...)
            mimeType = extensionMatch.getMimeType(); // 把 extensionMatch.getMimeType() 的返回值赋给 mimeType
        } // 代码块结束

        //上传文件的参数信息 // 保留原作者写的行内注释
        UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder() // 代码逻辑
                .bucket("testbucket")//桶 // 代码逻辑
                .filename("D:\\develop\\upload\\1.mp4") //指定本地文件路径 // 代码逻辑
//                .object("1.mp4")//对象名 在桶下存储该文件 // 保留原作者写的行内注释
                .object("test/01/1.mp4")//对象名 放在子目录下 // 代码逻辑
                .contentType(mimeType)//设置媒体文件类型 // 代码逻辑
                .build(); // 执行语句

        //上传文件 // 保留原作者写的行内注释
        minioClient.uploadObject(uploadObjectArgs); // 执行语句



    } // 代码块结束
    //删除文件 // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void test_delete() throws Exception { // 定义方法 test_delete(...)

        //RemoveObjectArgs // 保留原作者写的行内注释
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket("testbucket").object("1.mp4").build(); // 把 RemoveObjectArgs.builder().bucket("testbucket").object("1.mp4").build() 的返回值赋给 removeObjectArgs

        //删除文件 // 保留原作者写的行内注释
        minioClient.removeObject(removeObjectArgs); // 执行语句



    } // 代码块结束

    //查询文件 从minio中下载 // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void test_getFile() throws Exception { // 定义方法 test_getFile(...)

        GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("test/01/1.mp4").build(); // 把 GetObjectArgs.builder().bucket("testbucket").object("test/01/1.mp4").build() 的返回值赋给 getObjectArgs
        //查询远程服务获取到一个流对象 // 保留原作者写的行内注释
        FilterInputStream inputStream = minioClient.getObject(getObjectArgs); // 把 minioClient.getObject(getObjectArgs) 赋值给 inputStream
        //指定输出流 // 保留原作者写的行内注释
        FileOutputStream outputStream = new FileOutputStream(new File("D:\\develop\\upload\\1a.mp4")); // 创建 FileOutputStream 对象并赋值给 outputStream
        IOUtils.copy(inputStream,outputStream); // 执行语句

        //校验文件的完整性对文件的内容进行md5 // 保留原作者写的行内注释
        FileInputStream fileInputStream1 = new FileInputStream(new File("D:\\develop\\upload\\1.mp4")); // 创建 FileInputStream 对象并赋值给 fileInputStream1
        String source_md5 = DigestUtils.md5Hex(fileInputStream1); // 把 DigestUtils.md5Hex(fileInputStream1) 赋值给 source_md5
        FileInputStream fileInputStream = new FileInputStream(new File("D:\\develop\\upload\\1a.mp4")); // 创建 FileInputStream 对象并赋值给 fileInputStream
        String local_md5 = DigestUtils.md5Hex(fileInputStream); // 把 DigestUtils.md5Hex(fileInputStream) 赋值给 local_md5
        if(source_md5.equals(local_md5)){ // 定义方法 方法(...)
            System.out.println("下载成功"); // 执行语句
        } // 代码块结束

    } // 代码块结束


    //将分块文件上传到minio // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void uploadChunk() throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException { // 定义方法 uploadChunk(...)

        for (int i = 0; i < 6; i++) { // 定义方法 方法(...)
            //上传文件的参数信息 // 保留原作者写的行内注释
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder() // 代码逻辑
                    .bucket("testbucket")//桶 // 代码逻辑
                    .filename("D:\\develop\\upload\\chunk\\"+i) //指定本地文件路径 // 代码逻辑
                    .object("chunk/"+i)//对象名 放在子目录下 // 代码逻辑
                    .build(); // 执行语句

            //上传文件 // 保留原作者写的行内注释
            minioClient.uploadObject(uploadObjectArgs); // 执行语句
            System.out.println("上传分块"+i+"成功"); // 执行语句
        } // 代码块结束

    } // 代码块结束

    //调用minio接口合并分块 // 保留原作者写的行内注释
    @Test // 使用注解 @Test
    public void testMerge() throws Exception { // 定义方法 testMerge(...)

//        List<ComposeSource> sources = new ArrayList<>(); // 保留原作者写的行内注释
//        for (int i = 0; i < 30; i++) { // 保留原作者写的行内注释
//            //指定分块文件的信息 // 保留原作者写的行内注释
//            ComposeSource composeSource = ComposeSource.builder().bucket("testbucket").object("chunk/" + i).build(); // 保留原作者写的行内注释
//            sources.add(composeSource); // 保留原作者写的行内注释
//        } // 保留原作者写的行内注释

        List<ComposeSource> sources = Stream.iterate(0, i -> ++i).limit(6).map(i -> ComposeSource.builder().bucket("testbucket").object("chunk/" + i).build()).collect(Collectors.toList()); // 把 Stream.iterate(0, i -> ++i).limit(6).map(i -> ComposeSource.builder().bucket("testbucket").object("chunk/" + i).build()).collect(Collectors.toList()) 赋值给 sources

        //指定合并后的objectName等信息 // 保留原作者写的行内注释
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder() // 代码逻辑
                .bucket("testbucket") // 代码逻辑
                .object("merge01.mp4") // 代码逻辑
                .sources(sources)//指定源文件 // 代码逻辑
                .build(); // 执行语句
        //合并文件, // 保留原作者写的行内注释
        //报错size 1048576 must be greater than 5242880,minio默认的分块文件大小为5M // 保留原作者写的行内注释
        minioClient.composeObject(composeObjectArgs); // 执行语句

    } // 代码块结束



    //批量清理分块文件 // 保留原作者写的行内注释











} // 代码块结束
appendix_E
https://clxhxhhr.top/posts/4372/
作者
clxstart
发布于
2026-09-26
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。