feat(file): Add video management function

This commit is contained in:
sol 2025-07-23 14:29:35 +08:00
parent c87e0ffc65
commit d7092a5d75
9 changed files with 391 additions and 2 deletions

View file

@ -18,8 +18,8 @@ import lombok.experimental.SuperBuilder;
@TableName("t_image")
@Schema(description = "图片实体类")
public class ImageEntity extends BaseEntity {
@TableField("name")
@Schema(description = "图片名称")
@TableField("name")
private String name;
@Schema(description = "图片宽度")

View file

@ -0,0 +1,58 @@
package com.bgasol.model.file.video.dto;
import com.bgasol.common.core.base.dto.BaseCreateDto;
import com.bgasol.model.file.video.entity.VideoEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Setter
@Getter
@SuperBuilder
@NoArgsConstructor
@Schema(description = "创建视频实体类")
public class VideoCreateDto extends BaseCreateDto<VideoEntity> {
@Schema(description = "视频名称")
private String name;
@Schema(description = "视频宽度")
private Integer width;
@Schema(description = "视频高度")
private Integer height;
@Schema(description = "视频时长(秒)")
private Integer duration;
@Schema(description = "视频格式")
private String format;
@Schema(description = "视频码率")
private Integer bitrate;
@Schema(description = "视频帧率")
private Integer frameRate;
@Schema(description = "视频编码")
private String codec;
@Schema(description = "视频文件id")
private String fileId;
@Override
public VideoEntity toEntity() {
return this.toEntity(VideoEntity.builder()
.name(name)
.width(width)
.height(height)
.duration(duration)
.format(format)
.bitrate(bitrate)
.frameRate(frameRate)
.codec(codec)
.fileId(fileId)
.build());
}
}

View file

@ -0,0 +1,41 @@
package com.bgasol.model.file.video.dto;
import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bgasol.common.core.base.dto.BasePageDto;
import com.bgasol.model.file.video.entity.VideoEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.ObjectUtils;
@Setter
@Getter
@SuperBuilder
@NoArgsConstructor
@Schema(description = "图片分页查询参数")
public class VideoPageDto extends BasePageDto<VideoEntity> {
@Schema(description = "视频名称")
private String name;
@Schema(description = "大于(秒)视频时长")
private Integer duration;
@Schema(description = "视频格式")
private String format;
@Schema(description = "视频编码")
private String codec;
@Override
public AbstractLambdaWrapper<VideoEntity, LambdaQueryWrapper<VideoEntity>> getQueryWrapper() {
LambdaQueryWrapper<VideoEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(ObjectUtils.isNotEmpty(name), VideoEntity::getName, name);
queryWrapper.gt(ObjectUtils.isNotEmpty(duration), VideoEntity::getDuration, duration);
queryWrapper.eq(ObjectUtils.isNotEmpty(format), VideoEntity::getFormat, format);
queryWrapper.eq(ObjectUtils.isNotEmpty(codec), VideoEntity::getCodec, codec);
return queryWrapper;
}
}

View file

@ -0,0 +1,58 @@
package com.bgasol.model.file.video.dto;
import com.bgasol.common.core.base.dto.BaseUpdateDto;
import com.bgasol.model.file.video.entity.VideoEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Setter
@Getter
@SuperBuilder
@NoArgsConstructor
@Schema(description = "更新视频实体类")
public class VideoUpdateDto extends BaseUpdateDto<VideoEntity> {
@Schema(description = "视频名称")
private String name;
@Schema(description = "视频宽度")
private Integer width;
@Schema(description = "视频高度")
private Integer height;
@Schema(description = "视频时长(秒)")
private Integer duration;
@Schema(description = "视频格式")
private String format;
@Schema(description = "视频码率")
private Integer bitrate;
@Schema(description = "视频帧率")
private Integer frameRate;
@Schema(description = "视频编码")
private String codec;
@Schema(description = "视频文件id")
private String fileId;
@Override
public VideoEntity toEntity() {
return this.toEntity(VideoEntity.builder()
.name(name)
.width(width)
.height(height)
.duration(duration)
.format(format)
.bitrate(bitrate)
.frameRate(frameRate)
.codec(codec)
.fileId(fileId)
.build());
}
}

View file

@ -0,0 +1,65 @@
package com.bgasol.model.file.video.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.bgasol.common.core.base.entity.BaseEntity;
import com.bgasol.model.file.file.entity.FileEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Setter
@Getter
@SuperBuilder
@NoArgsConstructor
@TableName("t_video")
@Schema(description = "视频实体类")
public class VideoEntity extends BaseEntity {
@Schema(description = "视频名称")
@TableField("name")
private String name;
@Schema(description = "视频宽度")
@TableField("width")
private Integer width;
@Schema(description = "视频高度")
@TableField("height")
private Integer height;
@Schema(description = "视频时长(秒)")
@TableField("duration")
private Integer duration;
@Schema(description = "视频格式")
@TableField("format")
private String format;
@Schema(description = "视频码率")
@TableField("bitrate")
private Integer bitrate;
@Schema(description = "视频帧率")
@TableField("frame_rate")
private Integer frameRate;
@Schema(description = "视频编码")
@TableField("codec")
private String codec;
@Schema(description = "视频文件id")
@TableField("file_id")
@Transient
private String fileId;
@TableField(exist = false)
@Schema(description = "视频文件")
@OneToOne()
@JoinColumn(name = "file_id")
private FileEntity file;
}

View file

@ -83,7 +83,7 @@ public class ImageController extends BaseController<
}
@GetMapping("/download/{id}")
@Operation(summary = "下载图片", operationId = "downloadFile")
@Operation(summary = "下载图片", operationId = "downloadImage")
@SaCheckPermission("file:download")
public ResponseEntity<InputStreamResource> download(@PathVariable("id") String id) {
ImageEntity imageEntity = imageService.findById(id);

View file

@ -0,0 +1,100 @@
package com.bgasol.web.file.video.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.bgasol.common.core.base.controller.BaseController;
import com.bgasol.common.core.base.vo.BaseVo;
import com.bgasol.common.core.base.vo.PageVo;
import com.bgasol.model.file.file.entity.FileEntity;
import com.bgasol.model.file.video.dto.VideoCreateDto;
import com.bgasol.model.file.video.dto.VideoPageDto;
import com.bgasol.model.file.video.dto.VideoUpdateDto;
import com.bgasol.model.file.video.entity.VideoEntity;
import com.bgasol.web.file.file.service.FileService;
import com.bgasol.web.file.video.service.VideoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@RestController
@RequiredArgsConstructor
@Tag(name = "视频管理")
@RequestMapping("/video")
public class VideoController extends BaseController<
VideoEntity,
VideoPageDto,
VideoCreateDto,
VideoUpdateDto> {
private final VideoService videoService;
private final FileService fileService;
@Override
public VideoService commonBaseService() {
return videoService;
}
@Override
@PostMapping
@Operation(summary = "新增视频", operationId = "saveVideo")
@SaCheckPermission("video:save")
public BaseVo<VideoEntity> save(@RequestBody @Valid VideoCreateDto createDto) {
return super.save(createDto);
}
@Override
@PutMapping
@Operation(summary = "更新视频", operationId = "updateVideo")
@SaCheckPermission("video:update")
public BaseVo<VideoEntity> update(@RequestBody @Valid VideoUpdateDto updateDto) {
return super.update(updateDto);
}
@Override
@GetMapping("/{id}")
@Operation(summary = "查询视频", operationId = "findVideoById")
@SaCheckPermission("video:findById")
public BaseVo<VideoEntity> findById(@PathVariable String id) {
return super.findById(id);
}
@Override
@PostMapping("/page")
@Operation(summary = "分页查询视频", operationId = "findPageVideo")
@SaCheckPermission("video:findByPage")
public BaseVo<PageVo<VideoEntity>> findByPage(@RequestBody @Valid VideoPageDto pageDto) {
return super.findByPage(pageDto);
}
@Override
@DeleteMapping("/{ids}")
@Operation(summary = "删除视频", operationId = "deleteVideo")
@SaCheckPermission("video:delete")
public BaseVo<Integer[]> delete(@PathVariable String ids) {
return super.delete(ids);
}
@GetMapping("/download/{id}")
@Operation(summary = "下载视频", operationId = "downloadVideo")
@SaCheckPermission("video:download")
public ResponseEntity<InputStreamResource> download(@PathVariable("id") String id) {
VideoEntity videoEntity = videoService.findById(id);
FileEntity file = videoEntity.getFile();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.getSize()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(
fileService.getFileName(file),
StandardCharsets.UTF_8
))
.contentType(MediaType.valueOf(file.getType()))
.body(new InputStreamResource(videoService.videoStreamFindById(videoEntity.getId())));
}
}

View file

@ -0,0 +1,9 @@
package com.bgasol.web.file.video.mapper;
import com.bgasol.common.core.base.mapper.MyBaseMapper;
import com.bgasol.model.file.video.entity.VideoEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface VideoMapper extends MyBaseMapper<VideoEntity> {
}

View file

@ -0,0 +1,58 @@
package com.bgasol.web.file.video.service;
import com.bgasol.common.core.base.service.BaseService;
import com.bgasol.model.file.file.entity.FileEntity;
import com.bgasol.model.file.video.dto.VideoPageDto;
import com.bgasol.model.file.video.entity.VideoEntity;
import com.bgasol.web.file.file.service.FileService;
import com.bgasol.web.file.file.service.OssService;
import com.bgasol.web.file.video.mapper.VideoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class VideoService extends BaseService<VideoEntity, VideoPageDto> {
private final VideoMapper videoMapper;
private final FileService fileService;
private final RedissonClient redissonClient;
private final OssService ossService;
@Override
public RedissonClient commonBaseRedissonClient() {
return redissonClient;
}
@Override
public VideoMapper commonBaseMapper() {
return videoMapper;
}
@Override
@Transactional(readOnly = true)
public void findOtherTable(VideoEntity entity) {
if (ObjectUtils.isNotEmpty(entity.getFileId())) {
entity.setFile(fileService.findById(entity.getFileId()));
}
}
/**
* 读取图片文件流
*/
public InputStream videoStreamFindById(String id) {
VideoEntity imageEntity = this.findById(id);
FileEntity file = imageEntity.getFile();
return ossService.readFileStream(file.getBucket(), file.getId(), file.getName());
}
}