49677 字
约 165 分钟
47
appendix_E
2026-09-26
无标签
附录E 媒资服务模块源码详解
模块概览(面向 0 基础读者):
- 实现文件分片上传、合并校验、MinIO 存储与视频转码。
- 利用 XXL-Job 异步转码,结合 Redis、数据库跟踪处理进度。
- 向内容、学习等模块提供媒资绑定与访问接口。
核心目录:
xuecheng-plus-media/xuecheng-plus-media-api/src/main/java/com/xuecheng/media/apixuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/servicexuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/service/jobhandlerxuecheng-plus-media/xuecheng-plus-media-service/src/main/java/com/xuecheng/media/mapperxuecheng-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 语句片段 -->
<!–build 时强制覆盖 tag,配合 imageTags 使用–> <!-- SQL 语句片段 -->
<forceTags>true</forceTags> <!-- SQL 语句片段 -->
<!–build 完成后,push 指定 tag 的镜像,配合 imageTags 使用–> <!-- 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); // 执行语句
} // 代码块结束
//批量清理分块文件 // 保留原作者写的行内注释
} // 代码块结束
评论
0 条
还没有评论,先写一条吧。