diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/image/entity/ImageEntity.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/image/entity/ImageEntity.java index dbd0d46..f1163a8 100644 --- a/cloud/model/model-file/src/main/java/com/bgasol/model/file/image/entity/ImageEntity.java +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/image/entity/ImageEntity.java @@ -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 = "图片宽度") diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoCreateDto.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoCreateDto.java new file mode 100644 index 0000000..8f545b0 --- /dev/null +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoCreateDto.java @@ -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 { + @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()); + } +} diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoPageDto.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoPageDto.java new file mode 100644 index 0000000..ad766b5 --- /dev/null +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoPageDto.java @@ -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 { + @Schema(description = "视频名称") + private String name; + + @Schema(description = "大于(秒)视频时长") + private Integer duration; + + @Schema(description = "视频格式") + private String format; + + @Schema(description = "视频编码") + private String codec; + + @Override + public AbstractLambdaWrapper> getQueryWrapper() { + LambdaQueryWrapper 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; + } +} diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoUpdateDto.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoUpdateDto.java new file mode 100644 index 0000000..9ea0b02 --- /dev/null +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/dto/VideoUpdateDto.java @@ -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 { + @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()); + } +} diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/entity/VideoEntity.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/entity/VideoEntity.java new file mode 100644 index 0000000..db3c6c0 --- /dev/null +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/video/entity/VideoEntity.java @@ -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; +} diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/controller/ImageController.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/controller/ImageController.java index 6f659f8..bce058c 100644 --- a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/controller/ImageController.java +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/controller/ImageController.java @@ -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 download(@PathVariable("id") String id) { ImageEntity imageEntity = imageService.findById(id); diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/controller/VideoController.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/controller/VideoController.java new file mode 100644 index 0000000..04ca01d --- /dev/null +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/controller/VideoController.java @@ -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 save(@RequestBody @Valid VideoCreateDto createDto) { + return super.save(createDto); + } + + @Override + @PutMapping + @Operation(summary = "更新视频", operationId = "updateVideo") + @SaCheckPermission("video:update") + public BaseVo update(@RequestBody @Valid VideoUpdateDto updateDto) { + return super.update(updateDto); + } + + @Override + @GetMapping("/{id}") + @Operation(summary = "查询视频", operationId = "findVideoById") + @SaCheckPermission("video:findById") + public BaseVo findById(@PathVariable String id) { + return super.findById(id); + } + + @Override + @PostMapping("/page") + @Operation(summary = "分页查询视频", operationId = "findPageVideo") + @SaCheckPermission("video:findByPage") + public BaseVo> findByPage(@RequestBody @Valid VideoPageDto pageDto) { + return super.findByPage(pageDto); + } + + @Override + @DeleteMapping("/{ids}") + @Operation(summary = "删除视频", operationId = "deleteVideo") + @SaCheckPermission("video:delete") + public BaseVo delete(@PathVariable String ids) { + return super.delete(ids); + } + + @GetMapping("/download/{id}") + @Operation(summary = "下载视频", operationId = "downloadVideo") + @SaCheckPermission("video:download") + public ResponseEntity 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()))); + } +} diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/mapper/VideoMapper.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/mapper/VideoMapper.java new file mode 100644 index 0000000..6c4cb43 --- /dev/null +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/mapper/VideoMapper.java @@ -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 { +} diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/service/VideoService.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/service/VideoService.java new file mode 100644 index 0000000..77f2d59 --- /dev/null +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/video/service/VideoService.java @@ -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 { + 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()); + } +}