From 56acac87597c52a67ab96477623cfb7c07515ced Mon Sep 17 00:00:00 2001 From: smile <1372184840@qq.com> Date: Fri, 19 Sep 2025 16:04:40 +0800 Subject: [PATCH] feat(file): Object storage persistence follows preset path rules --- client/src/generated/file/core/OpenAPI.ts | 2 +- client/src/generated/file/index.ts | 7 + .../file/models/BaseVoPageVoVideoEntity.ts | 39 ++++ .../file/models/BaseVoVideoEntity.ts | 39 ++++ .../generated/file/models/FileCreateDto.ts | 3 + .../generated/file/models/FileUpdateDto.ts | 21 ++- .../file/models/PageVoVideoEntity.ts | 27 +++ .../generated/file/models/VideoCreateDto.ts | 54 ++++++ .../src/generated/file/models/VideoEntity.ts | 73 ++++++++ .../src/generated/file/models/VideoPageDto.ts | 34 ++++ .../generated/file/models/VideoUpdateDto.ts | 58 ++++++ client/src/generated/file/services/Service.ts | 174 ++++++++++++++++-- .../src/generated/system/services/Service.ts | 25 ++- .../common/core/base/service/BaseService.java | 1 - .../model/file/file/dto/FileCreateDto.java | 4 + .../model/file/file/dto/FileUpdateDto.java | 3 - .../file/file/controller/FileController.java | 4 +- .../web/file/file/service/FileService.java | 12 +- .../web/file/file/service/OssService.java | 54 ++++-- .../web/file/image/service/ImageService.java | 2 +- .../web/file/video/service/VideoService.java | 2 +- 21 files changed, 589 insertions(+), 49 deletions(-) create mode 100644 client/src/generated/file/models/BaseVoPageVoVideoEntity.ts create mode 100644 client/src/generated/file/models/BaseVoVideoEntity.ts create mode 100644 client/src/generated/file/models/PageVoVideoEntity.ts create mode 100644 client/src/generated/file/models/VideoCreateDto.ts create mode 100644 client/src/generated/file/models/VideoEntity.ts create mode 100644 client/src/generated/file/models/VideoPageDto.ts create mode 100644 client/src/generated/file/models/VideoUpdateDto.ts diff --git a/client/src/generated/file/core/OpenAPI.ts b/client/src/generated/file/core/OpenAPI.ts index 5592825..59aaa8b 100644 --- a/client/src/generated/file/core/OpenAPI.ts +++ b/client/src/generated/file/core/OpenAPI.ts @@ -20,7 +20,7 @@ export type OpenAPIConfig = { }; export const OpenAPI: OpenAPIConfig = { - BASE: 'http://localhost:9527/file', + BASE: '/file', VERSION: '1.0.0', WITH_CREDENTIALS: false, CREDENTIALS: 'include', diff --git a/client/src/generated/file/index.ts b/client/src/generated/file/index.ts index fc8a979..4ae7708 100644 --- a/client/src/generated/file/index.ts +++ b/client/src/generated/file/index.ts @@ -14,6 +14,8 @@ export { BaseVoListVerificationResult } from './models/BaseVoListVerificationRes export { BaseVoObject } from './models/BaseVoObject'; export { BaseVoPageVoFileEntity } from './models/BaseVoPageVoFileEntity'; export { BaseVoPageVoImageEntity } from './models/BaseVoPageVoImageEntity'; +export { BaseVoPageVoVideoEntity } from './models/BaseVoPageVoVideoEntity'; +export { BaseVoVideoEntity } from './models/BaseVoVideoEntity'; export type { FileCreateDto } from './models/FileCreateDto'; export type { FileEntity } from './models/FileEntity'; export type { FilePageDto } from './models/FilePageDto'; @@ -24,6 +26,11 @@ export type { ImagePageDto } from './models/ImagePageDto'; export type { ImageUpdateDto } from './models/ImageUpdateDto'; export type { PageVoFileEntity } from './models/PageVoFileEntity'; export type { PageVoImageEntity } from './models/PageVoImageEntity'; +export type { PageVoVideoEntity } from './models/PageVoVideoEntity'; export type { VerificationResult } from './models/VerificationResult'; +export type { VideoCreateDto } from './models/VideoCreateDto'; +export type { VideoEntity } from './models/VideoEntity'; +export type { VideoPageDto } from './models/VideoPageDto'; +export type { VideoUpdateDto } from './models/VideoUpdateDto'; export { Service } from './services/Service'; diff --git a/client/src/generated/file/models/BaseVoPageVoVideoEntity.ts b/client/src/generated/file/models/BaseVoPageVoVideoEntity.ts new file mode 100644 index 0000000..e60d39e --- /dev/null +++ b/client/src/generated/file/models/BaseVoPageVoVideoEntity.ts @@ -0,0 +1,39 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { PageVoVideoEntity } from './PageVoVideoEntity'; +/** + * 基础响应数据 + */ +export type BaseVoPageVoVideoEntity = { + /** + * 响应码 + */ + code?: number; + /** + * 响应消息 + */ + message?: string; + data?: PageVoVideoEntity; + /** + * 响应时间 + */ + time?: string; + /** + * 响应类型 + */ + type?: BaseVoPageVoVideoEntity.type; +}; +export namespace BaseVoPageVoVideoEntity { + /** + * 响应类型 + */ + export enum type { + SUCCESS = 'SUCCESS', + WARNING = 'WARNING', + INFO = 'INFO', + ERROR = 'ERROR', + } +} + diff --git a/client/src/generated/file/models/BaseVoVideoEntity.ts b/client/src/generated/file/models/BaseVoVideoEntity.ts new file mode 100644 index 0000000..aac242d --- /dev/null +++ b/client/src/generated/file/models/BaseVoVideoEntity.ts @@ -0,0 +1,39 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { VideoEntity } from './VideoEntity'; +/** + * 基础响应数据 + */ +export type BaseVoVideoEntity = { + /** + * 响应码 + */ + code?: number; + /** + * 响应消息 + */ + message?: string; + data?: VideoEntity; + /** + * 响应时间 + */ + time?: string; + /** + * 响应类型 + */ + type?: BaseVoVideoEntity.type; +}; +export namespace BaseVoVideoEntity { + /** + * 响应类型 + */ + export enum type { + SUCCESS = 'SUCCESS', + WARNING = 'WARNING', + INFO = 'INFO', + ERROR = 'ERROR', + } +} + diff --git a/client/src/generated/file/models/FileCreateDto.ts b/client/src/generated/file/models/FileCreateDto.ts index 255bdb4..e759654 100644 --- a/client/src/generated/file/models/FileCreateDto.ts +++ b/client/src/generated/file/models/FileCreateDto.ts @@ -15,6 +15,9 @@ export type FileCreateDto = { */ description?: string; uploadFile?: Blob; + /** + * 文件名称 + */ name?: string; /** * 文件状态 diff --git a/client/src/generated/file/models/FileUpdateDto.ts b/client/src/generated/file/models/FileUpdateDto.ts index a11c83e..ad0e65c 100644 --- a/client/src/generated/file/models/FileUpdateDto.ts +++ b/client/src/generated/file/models/FileUpdateDto.ts @@ -9,16 +9,11 @@ export type FileUpdateDto = { /** * 主键 */ - id: string; - /** - * 排序 - */ - sort?: number; - /** - * 描述 - */ - description?: string; + id?: string; uploadFile?: Blob; + /** + * 文件名称 + */ name?: string; /** * 文件状态 @@ -32,5 +27,13 @@ export type FileUpdateDto = { * 文件来源 */ source?: string; + /** + * 排序 + */ + sort?: number; + /** + * 描述 + */ + description?: string; }; diff --git a/client/src/generated/file/models/PageVoVideoEntity.ts b/client/src/generated/file/models/PageVoVideoEntity.ts new file mode 100644 index 0000000..c0966d8 --- /dev/null +++ b/client/src/generated/file/models/PageVoVideoEntity.ts @@ -0,0 +1,27 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { VideoEntity } from './VideoEntity'; +/** + * 分页响应数据 + */ +export type PageVoVideoEntity = { + /** + * 总条数 + */ + total?: number; + /** + * 当前页码 + */ + page?: number; + /** + * 每页条数 + */ + size?: number; + /** + * 响应数据 + */ + result?: Array; +}; + diff --git a/client/src/generated/file/models/VideoCreateDto.ts b/client/src/generated/file/models/VideoCreateDto.ts new file mode 100644 index 0000000..6c9d9a2 --- /dev/null +++ b/client/src/generated/file/models/VideoCreateDto.ts @@ -0,0 +1,54 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * 创建视频实体类 + */ +export type VideoCreateDto = { + /** + * 排序 + */ + sort?: number; + /** + * 描述 + */ + description?: string; + /** + * 视频名称 + */ + name?: string; + /** + * 视频宽度 + */ + width?: number; + /** + * 视频高度 + */ + height?: number; + /** + * 视频时长(秒) + */ + duration?: number; + /** + * 视频格式 + */ + format?: string; + /** + * 视频码率 + */ + bitrate?: number; + /** + * 视频帧率 + */ + fps?: number; + /** + * 视频编码 + */ + codec?: string; + /** + * 视频文件id + */ + fileId?: string; +}; + diff --git a/client/src/generated/file/models/VideoEntity.ts b/client/src/generated/file/models/VideoEntity.ts new file mode 100644 index 0000000..e8a7cb7 --- /dev/null +++ b/client/src/generated/file/models/VideoEntity.ts @@ -0,0 +1,73 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { FileEntity } from './FileEntity'; +/** + * 视频实体类 + */ +export type VideoEntity = { + id?: string; + /** + * 类型 + */ + type?: string; + /** + * 排序 + */ + sort?: number; + /** + * 创建时间 + */ + createTime?: string; + /** + * 更新时间 + */ + updateTime?: string; + /** + * 描述 + */ + description?: string; + /** + * 是否删除 + */ + deleted?: number; + /** + * 视频名称 + */ + name?: string; + /** + * 视频宽度 + */ + width?: number; + /** + * 视频高度 + */ + height?: number; + /** + * 视频时长(秒) + */ + duration?: number; + /** + * 视频格式 + */ + format?: string; + /** + * 视频码率 + */ + bitrate?: number; + /** + * 视频帧率 + */ + fps?: number; + /** + * 视频编码 + */ + codec?: string; + /** + * 视频文件id + */ + fileId?: string; + file?: FileEntity; +}; + diff --git a/client/src/generated/file/models/VideoPageDto.ts b/client/src/generated/file/models/VideoPageDto.ts new file mode 100644 index 0000000..3bfc088 --- /dev/null +++ b/client/src/generated/file/models/VideoPageDto.ts @@ -0,0 +1,34 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * 图片分页查询参数 + */ +export type VideoPageDto = { + /** + * 页码 + */ + page: number; + /** + * 每页条数 + */ + size: number; + /** + * 视频名称 + */ + name?: string; + /** + * 大于(秒)视频时长 + */ + duration?: number; + /** + * 视频格式 + */ + format?: string; + /** + * 视频编码 + */ + codec?: string; +}; + diff --git a/client/src/generated/file/models/VideoUpdateDto.ts b/client/src/generated/file/models/VideoUpdateDto.ts new file mode 100644 index 0000000..e1a8429 --- /dev/null +++ b/client/src/generated/file/models/VideoUpdateDto.ts @@ -0,0 +1,58 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * 更新视频实体类 + */ +export type VideoUpdateDto = { + /** + * 主键 + */ + id: string; + /** + * 排序 + */ + sort?: number; + /** + * 描述 + */ + description?: string; + /** + * 视频名称 + */ + name?: string; + /** + * 视频宽度 + */ + width?: number; + /** + * 视频高度 + */ + height?: number; + /** + * 视频时长(秒) + */ + duration?: number; + /** + * 视频格式 + */ + format?: string; + /** + * 视频码率 + */ + bitrate?: number; + /** + * 视频帧率 + */ + fps?: number; + /** + * 视频编码 + */ + codec?: string; + /** + * 视频文件id + */ + fileId?: string; +}; + diff --git a/client/src/generated/file/services/Service.ts b/client/src/generated/file/services/Service.ts index 2818627..d1c5cbc 100644 --- a/client/src/generated/file/services/Service.ts +++ b/client/src/generated/file/services/Service.ts @@ -7,16 +7,61 @@ import type { BaseVoImageEntity } from '../models/BaseVoImageEntity'; import type { BaseVoInteger } from '../models/BaseVoInteger'; import type { BaseVoPageVoFileEntity } from '../models/BaseVoPageVoFileEntity'; import type { BaseVoPageVoImageEntity } from '../models/BaseVoPageVoImageEntity'; +import type { BaseVoPageVoVideoEntity } from '../models/BaseVoPageVoVideoEntity'; +import type { BaseVoVideoEntity } from '../models/BaseVoVideoEntity'; import type { FileCreateDto } from '../models/FileCreateDto'; import type { FilePageDto } from '../models/FilePageDto'; import type { FileUpdateDto } from '../models/FileUpdateDto'; import type { ImageCreateDto } from '../models/ImageCreateDto'; import type { ImagePageDto } from '../models/ImagePageDto'; import type { ImageUpdateDto } from '../models/ImageUpdateDto'; +import type { VideoCreateDto } from '../models/VideoCreateDto'; +import type { VideoPageDto } from '../models/VideoPageDto'; +import type { VideoUpdateDto } from '../models/VideoUpdateDto'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; export class Service { + /** + * 更新视频 + * @param requestBody + * @returns BaseVoVideoEntity OK + * @throws ApiError + */ + public static updateVideo( + requestBody: VideoUpdateDto, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/video', + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } + /** + * 新增视频 + * @param requestBody + * @returns BaseVoVideoEntity OK + * @throws ApiError + */ + public static saveVideo( + requestBody: VideoCreateDto, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/video', + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } /** * 更新图片 * @param requestBody @@ -59,19 +104,18 @@ export class Service { } /** * 更新|上传文件 - * @param fileUpdateDto + * @param formData * @returns BaseVoFileEntity OK * @throws ApiError */ public static updateFile( - fileUpdateDto: FileUpdateDto, + formData?: FileUpdateDto, ): CancelablePromise { return __request(OpenAPI, { method: 'PUT', url: '/file', - query: { - 'fileUpdateDto': fileUpdateDto, - }, + formData: formData, + mediaType: 'multipart/form-data', errors: { 400: `参数校验异常`, 500: `业务异常`, @@ -80,19 +124,38 @@ export class Service { } /** * 保存|上传文件 - * @param fileCreateDto + * @param formData * @returns BaseVoFileEntity OK * @throws ApiError */ public static saveFile( - fileCreateDto: FileCreateDto, + formData?: FileCreateDto, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/file', - query: { - 'fileCreateDto': fileCreateDto, + formData: formData, + mediaType: 'multipart/form-data', + errors: { + 400: `参数校验异常`, + 500: `业务异常`, }, + }); + } + /** + * 分页查询视频 + * @param requestBody + * @returns BaseVoPageVoVideoEntity OK + * @throws ApiError + */ + public static findPageVideo( + requestBody: VideoPageDto, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/video/page', + body: requestBody, + mediaType: 'application/json', errors: { 400: `参数校验异常`, 500: `业务异常`, @@ -139,6 +202,48 @@ export class Service { }, }); } + /** + * 查询视频 + * @param id + * @returns BaseVoVideoEntity OK + * @throws ApiError + */ + public static findVideoById( + id: string, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/video/{id}', + path: { + 'id': id, + }, + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } + /** + * 下载视频 + * @param id + * @returns binary OK + * @throws ApiError + */ + public static downloadVideo( + id: string, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/video/download/{id}', + path: { + 'id': id, + }, + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } /** * 查询图片 * @param id @@ -166,7 +271,7 @@ export class Service { * @returns binary OK * @throws ApiError */ - public static downloadFile( + public static downloadImage( id: string, ): CancelablePromise { return __request(OpenAPI, { @@ -202,13 +307,39 @@ export class Service { }, }); } + /** + * 在线播放文件 + * @param id + * @param range + * @returns binary OK + * @throws ApiError + */ + public static streamFile( + id: string, + range?: string, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/file/stream/{id}', + path: { + 'id': id, + }, + headers: { + 'Range': range, + }, + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } /** * 下载文件 * @param id * @returns binary OK * @throws ApiError */ - public static downloadFile1( + public static downloadFile( id: string, ): CancelablePromise { return __request(OpenAPI, { @@ -223,6 +354,27 @@ export class Service { }, }); } + /** + * 删除视频 + * @param ids + * @returns BaseVoInteger OK + * @throws ApiError + */ + public static deleteVideo( + ids: string, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/video/{ids}', + path: { + 'ids': ids, + }, + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } /** * 删除图片 * @param ids diff --git a/client/src/generated/system/services/Service.ts b/client/src/generated/system/services/Service.ts index 1757300..14f54d5 100644 --- a/client/src/generated/system/services/Service.ts +++ b/client/src/generated/system/services/Service.ts @@ -430,10 +430,10 @@ export class Service { } /** * 下载角色导入模板 - * @returns string OK + * @returns binary OK * @throws ApiError */ - public static downloadRoleImportTemplate(): CancelablePromise { + public static downloadRoleImportTemplate(): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/role/template-download', @@ -509,6 +509,27 @@ export class Service { }, }); } + /** + * 查询指定菜单组下的菜单 + * @param group + * @returns BaseVoListMenuEntity OK + * @throws ApiError + */ + public static findByMenuGroup( + group: string, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/menu/find-by-menu-group/{group}', + path: { + 'group': group, + }, + errors: { + 400: `参数校验异常`, + 500: `业务异常`, + }, + }); + } /** * 查询管理员菜单组 * @returns BaseVoListMenuEntity OK diff --git a/cloud/common/common-base-web/src/main/java/com/bgasol/common/core/base/service/BaseService.java b/cloud/common/common-base-web/src/main/java/com/bgasol/common/core/base/service/BaseService.java index 953c90b..f9caaff 100644 --- a/cloud/common/common-base-web/src/main/java/com/bgasol/common/core/base/service/BaseService.java +++ b/cloud/common/common-base-web/src/main/java/com/bgasol/common/core/base/service/BaseService.java @@ -2,7 +2,6 @@ package com.bgasol.common.core.base.service; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.bgasol.common.core.base.dto.BasePageDto; diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileCreateDto.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileCreateDto.java index 12cd6b5..ed52f17 100644 --- a/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileCreateDto.java +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileCreateDto.java @@ -8,6 +8,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.SuperBuilder; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.web.multipart.MultipartFile; import static com.bgasol.model.file.file.mapstruct.FileMapstruct.FILE_MAPSTRUCT_IMPL; @@ -37,6 +38,9 @@ public class FileCreateDto extends BaseCreateDto { @JsonIgnore @Schema(hidden = true) public FileEntity toEntity() { + if (ObjectUtils.isEmpty(this.source)) { + this.source = "default"; + } return super.toEntity(FILE_MAPSTRUCT_IMPL.toEntity(this)); } } diff --git a/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileUpdateDto.java b/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileUpdateDto.java index 447aa90..2f9a5ec 100644 --- a/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileUpdateDto.java +++ b/cloud/model/model-file/src/main/java/com/bgasol/model/file/file/dto/FileUpdateDto.java @@ -32,9 +32,6 @@ public class FileUpdateDto { @Schema(description = "文件后缀") private String suffix; - @Schema(description = "文件来源") - private String source; - @Schema(description = "排序") private Integer sort; diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/controller/FileController.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/controller/FileController.java index 7781e56..114ead5 100644 --- a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/controller/FileController.java +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/controller/FileController.java @@ -101,7 +101,7 @@ public class FileController extends BaseController< StandardCharsets.UTF_8 )) .contentType(MediaType.valueOf(file.getType())) - .body(new InputStreamResource(ossService.readFileStream(file.getBucket(), file.getId(), file.getName()))); + .body(new InputStreamResource(ossService.readFileStream(file))); } @GetMapping("/stream/{id}") @@ -134,7 +134,7 @@ public class FileController extends BaseController< long contentLength = rangeEnd - rangeStart + 1; - InputStream inputStream = ossService.readFileStream(file.getBucket(), file.getId(), file.getName()); + InputStream inputStream = ossService.readFileStream(file); inputStream.skip(rangeStart); // 跳到起始位置 InputStreamResource resource = new InputStreamResource(inputStream); diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/FileService.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/FileService.java index 65db39e..495b886 100644 --- a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/FileService.java +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/FileService.java @@ -19,6 +19,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; +import java.util.Date; @Service @RequiredArgsConstructor @@ -29,8 +30,6 @@ public class FileService extends BaseService { private final MinioConfig minioConfig; - private final MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap(); - private final OssService ossService; private final RedissonClient redissonClient; @@ -58,7 +57,7 @@ public class FileService extends BaseService { fileEntity = this.save(fileEntity); // 上传文件 try (InputStream inputStream = multipartFile.getInputStream()) { - ossService.writeFileStream(fileEntity.getBucket(), fileEntity.getId(), fileEntity.getName(), inputStream, fileEntity.getSize(), fileEntity.getType()); + ossService.writeFileStream(inputStream, fileEntity); } catch (IOException e) { throw new BaseException("上传文件失败"); } @@ -75,7 +74,7 @@ public class FileService extends BaseService { fileEntity = this.update(fileEntity); // 上传文件 try (InputStream inputStream = multipartFile.getInputStream()) { - ossService.writeFileStream(fileEntity.getBucket(), fileEntity.getId(), fileEntity.getName(), inputStream, fileEntity.getSize(), fileEntity.getType()); + ossService.writeFileStream(inputStream, fileEntity); } catch (IOException e) { throw new BaseException("上传文件失败"); } @@ -105,6 +104,7 @@ public class FileService extends BaseService { throw new BaseException("获取文件HASH失败"); } fileEntity.setBucket(minioConfig.getBucket()); + fileEntity.setCreateTime(new Date()); } /** @@ -147,7 +147,7 @@ public class FileService extends BaseService { if (fileEntity == null) { throw new BaseException("文件不存在"); } - ossService.removeFile(fileEntity.getBucket(), fileEntity.getId()); + ossService.removeFile(fileEntity); return super.delete(id); } @@ -170,6 +170,6 @@ public class FileService extends BaseService { */ public InputStream fileStreamFindById(String id) { FileEntity file = this.findById(id); - return ossService.readFileStream(file.getBucket(), file.getId(), file.getName()); + return ossService.readFileStream(file); } } diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/OssService.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/OssService.java index 35e21b9..dd2eee1 100644 --- a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/OssService.java +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/file/service/OssService.java @@ -1,6 +1,7 @@ package com.bgasol.web.file.file.service; import com.bgasol.common.core.base.exception.BaseException; +import com.bgasol.model.file.file.entity.FileEntity; import io.minio.GetObjectArgs; import io.minio.MinioClient; import io.minio.PutObjectArgs; @@ -8,6 +9,7 @@ import io.minio.RemoveObjectArgs; import io.minio.errors.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,6 +17,10 @@ import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Date; @Service @RequiredArgsConstructor @@ -23,18 +29,26 @@ import java.security.NoSuchAlgorithmException; public class OssService { private final MinioClient minioClient; + private static final String FILE_SEPARATOR = ":"; + /** * 写入文件流到对象存储 */ - public void writeFileStream(String bucket, String id, String name, InputStream inputStream, Long size, String type) { + public void writeFileStream(InputStream inputStream, FileEntity file) { try { + LocalDate localDate = file.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + String dateStr = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "/"; + + String source = file.getSource(); + source = ObjectUtils.isEmpty(source) ? "" : source + "/"; + // 创建上传文件参数 PutObjectArgs objectArgs = PutObjectArgs .builder() - .bucket(bucket) - .object(id + ":" + name) - .stream(inputStream, size, -1) - .contentType(type) + .bucket(file.getBucket()) + .object(dateStr + source + file.getId() + FILE_SEPARATOR + file.getName()) + .stream(inputStream, file.getSize(), -1) + .contentType(file.getType()) .build(); // 上传文件到minio id 相同会覆盖 minioClient.putObject(objectArgs); @@ -50,16 +64,16 @@ public class OssService { /** * 从对象存储获取文件流 * - * @param id 文件id * @return 文件流 */ @Transactional(readOnly = true) - public InputStream readFileStream(String bucket, String id, String name) { + public InputStream readFileStream(FileEntity file) { try { + GetObjectArgs build = GetObjectArgs .builder() - .bucket(bucket) - .object(id + ":" + name) + .bucket(file.getBucket()) + .object(buildObjectPath(file)) .build(); // 获取文件流 return minioClient.getObject(build); @@ -71,15 +85,17 @@ public class OssService { } } + /** * 从对象存储中移除文件 */ - public void removeFile(String bucket, String id) { + public void removeFile(FileEntity file) { try { + RemoveObjectArgs build = RemoveObjectArgs .builder() - .bucket(bucket) - .object(id) + .bucket(file.getBucket()) + .object(buildObjectPath(file)) .build(); minioClient.removeObject(build); } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | @@ -89,4 +105,18 @@ public class OssService { throw new BaseException("文件删除失败"); } } + + /** + * 构建对象存储路径 + */ + private String buildObjectPath(FileEntity file) { + Date createTime = file.getCreateTime(); + LocalDate localDate = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + String dateStr = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "/"; + + String source = file.getSource(); + source = ObjectUtils.isEmpty(source) ? "" : source + "/"; + + return dateStr + source + file.getId() + FILE_SEPARATOR + file.getName(); + } } diff --git a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/service/ImageService.java b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/service/ImageService.java index d0d3858..9d1a9d4 100644 --- a/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/service/ImageService.java +++ b/cloud/web/web-file-8082/src/main/java/com/bgasol/web/file/image/service/ImageService.java @@ -85,7 +85,7 @@ public class ImageService extends BaseService { public InputStream imageStreamFindById(String id) { ImageEntity imageEntity = this.findById(id); FileEntity file = imageEntity.getFile(); - return ossService.readFileStream(file.getBucket(), file.getId(), file.getName()); + return ossService.readFileStream(file); } /** 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 index 77f2d59..f5d677d 100644 --- 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 @@ -53,6 +53,6 @@ public class VideoService extends BaseService { public InputStream videoStreamFindById(String id) { VideoEntity imageEntity = this.findById(id); FileEntity file = imageEntity.getFile(); - return ossService.readFileStream(file.getBucket(), file.getId(), file.getName()); + return ossService.readFileStream(file); } }