Commit 87670d18fdf8c96f5a61861b41381d8adf9cecc7
1 parent
cdcecd0d
完成新 File 的功能
Showing
25 changed files
with
258 additions
and
186 deletions
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java
| 1 | 1 | package cn.iocoder.yudao.framework.file.core.client; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.StrUtil; |
| 4 | -import cn.iocoder.yudao.framework.file.core.client.FileClient; | |
| 5 | -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; | |
| 6 | 4 | import lombok.extern.slf4j.Slf4j; |
| 7 | 5 | |
| 8 | 6 | /** |
| ... | ... | @@ -65,7 +63,7 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> implem |
| 65 | 63 | * @return URL 访问地址 |
| 66 | 64 | */ |
| 67 | 65 | protected String formatFileUrl(String domain, String path) { |
| 68 | - return StrUtil.format("{}/system-api/{}/get/{}", domain, getId(), path); | |
| 66 | + return StrUtil.format("{}/admin-api/infra/file/{}/get/{}", domain, getId(), path); | |
| 69 | 67 | } |
| 70 | 68 | |
| 71 | 69 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java
| ... | ... | @@ -18,24 +18,31 @@ public class DBFileClient extends AbstractFileClient<DBFileClientConfig> { |
| 18 | 18 | |
| 19 | 19 | @Override |
| 20 | 20 | protected void doInit() { |
| 21 | - dao = SpringUtil.getBean(DBFileContentFrameworkDAO.class); | |
| 22 | 21 | } |
| 23 | 22 | |
| 24 | 23 | @Override |
| 25 | 24 | public String upload(byte[] content, String path) { |
| 26 | - dao.insert(getId(), path, content); | |
| 25 | + getDao().insert(getId(), path, content); | |
| 27 | 26 | // 拼接返回路径 |
| 28 | 27 | return super.formatFileUrl(config.getDomain(), path); |
| 29 | 28 | } |
| 30 | 29 | |
| 31 | 30 | @Override |
| 32 | 31 | public void delete(String path) { |
| 33 | - dao.delete(getId(), path); | |
| 32 | + getDao().delete(getId(), path); | |
| 34 | 33 | } |
| 35 | 34 | |
| 36 | 35 | @Override |
| 37 | 36 | public byte[] getContent(String path) { |
| 38 | - return dao.selectContent(getId(), path); | |
| 37 | + return getDao().selectContent(getId(), path); | |
| 38 | + } | |
| 39 | + | |
| 40 | + private DBFileContentFrameworkDAO getDao() { | |
| 41 | + // 延迟获取,因为 SpringUtil 初始化太慢 | |
| 42 | + if (dao == null) { | |
| 43 | + dao = SpringUtil.getBean(DBFileContentFrameworkDAO.class); | |
| 44 | + } | |
| 45 | + return dao; | |
| 39 | 46 | } |
| 40 | 47 | |
| 41 | 48 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java
| ... | ... | @@ -7,10 +7,30 @@ package cn.iocoder.yudao.framework.file.core.client.db; |
| 7 | 7 | */ |
| 8 | 8 | public interface DBFileContentFrameworkDAO { |
| 9 | 9 | |
| 10 | + /** | |
| 11 | + * 插入文件内容 | |
| 12 | + * | |
| 13 | + * @param configId 配置编号 | |
| 14 | + * @param path 路径 | |
| 15 | + * @param content 内容 | |
| 16 | + */ | |
| 10 | 17 | void insert(Long configId, String path, byte[] content); |
| 11 | 18 | |
| 19 | + /** | |
| 20 | + * 删除文件内容 | |
| 21 | + * | |
| 22 | + * @param configId 配置编号 | |
| 23 | + * @param path 路径 | |
| 24 | + */ | |
| 12 | 25 | void delete(Long configId, String path); |
| 13 | 26 | |
| 27 | + /** | |
| 28 | + * 获得文件内容 | |
| 29 | + * | |
| 30 | + * @param configId 配置编号 | |
| 31 | + * @param path 路径 | |
| 32 | + * @return 内容 | |
| 33 | + */ | |
| 14 | 34 | byte[] selectContent(Long configId, String path); |
| 15 | 35 | |
| 16 | 36 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
| ... | ... | @@ -4,8 +4,8 @@ import cn.hutool.core.io.IoUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 7 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; | |
| 8 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FileRespVO; | |
| 7 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | |
| 8 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; | |
| 9 | 9 | import cn.iocoder.yudao.module.infra.convert.file.FileConvert; |
| 10 | 10 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 11 | 11 | import cn.iocoder.yudao.module.infra.service.file.FileService; |
| ... | ... | @@ -50,9 +50,9 @@ public class FileController { |
| 50 | 50 | |
| 51 | 51 | @DeleteMapping("/delete") |
| 52 | 52 | @ApiOperation("删除文件") |
| 53 | - @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = String.class) | |
| 53 | + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | |
| 54 | 54 | @PreAuthorize("@ss.hasPermission('infra:file:delete')") |
| 55 | - public CommonResult<Boolean> deleteFile(@RequestParam("id") String id) { | |
| 55 | + public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) { | |
| 56 | 56 | fileService.deleteFile(id); |
| 57 | 57 | return success(true); |
| 58 | 58 | } |
| ... | ... | @@ -60,19 +60,19 @@ public class FileController { |
| 60 | 60 | @GetMapping("/{configId}/get/{path}") |
| 61 | 61 | @ApiOperation("下载文件") |
| 62 | 62 | @ApiImplicitParams({ |
| 63 | - @ApiImplicitParam(name = "configId", value = "配置编号", required = true, dataTypeClass = String.class), | |
| 63 | + @ApiImplicitParam(name = "configId", value = "配置编号", required = true, dataTypeClass = Long.class), | |
| 64 | 64 | @ApiImplicitParam(name = "path", value = "文件路径", required = true, dataTypeClass = String.class) |
| 65 | 65 | }) |
| 66 | - public void getFile(HttpServletResponse response, | |
| 67 | - @PathVariable("configId") String configId, | |
| 68 | - @PathVariable("path") String path) throws IOException { | |
| 69 | - FileDO file = fileService.getFile(path); | |
| 70 | - if (file == null) { | |
| 71 | - log.warn("[getFile][path({}) 文件不存在]", path); | |
| 66 | + public void getFileContent(HttpServletResponse response, | |
| 67 | + @PathVariable("configId") Long configId, | |
| 68 | + @PathVariable("path") String path) throws IOException { | |
| 69 | + byte[] content = fileService.getFileContent(configId, path); | |
| 70 | + if (content == null) { | |
| 71 | + log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path); | |
| 72 | 72 | response.setStatus(HttpStatus.NOT_FOUND.value()); |
| 73 | 73 | return; |
| 74 | 74 | } |
| 75 | - ServletUtils.writeAttachment(response, path, file.getContent()); | |
| 75 | + ServletUtils.writeAttachment(response, path, content); | |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | @GetMapping("/page") | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FilePageReqVO.java renamed to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
| 1 | -package cn.iocoder.yudao.module.infra.controller.admin.file.vo; | |
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; | |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | 4 | import io.swagger.annotations.ApiModel; |
| ... | ... | @@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 19 | 19 | public class FilePageReqVO extends PageParam { |
| 20 | 20 | |
| 21 | 21 | @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配") |
| 22 | - private String id; | |
| 22 | + private String path; | |
| 23 | 23 | |
| 24 | 24 | @ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配") |
| 25 | 25 | private String type; | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FileRespVO.java renamed to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
| 1 | -package cn.iocoder.yudao.module.infra.controller.admin.file.vo; | |
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.annotations.ApiModel; |
| 4 | 4 | import io.swagger.annotations.ApiModelProperty; |
| ... | ... | @@ -10,12 +10,21 @@ import java.util.Date; |
| 10 | 10 | @Data |
| 11 | 11 | public class FileRespVO { |
| 12 | 12 | |
| 13 | + @ApiModelProperty(value = "文件编号", required = true, example = "1024") | |
| 14 | + private Long id; | |
| 15 | + | |
| 13 | 16 | @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg") |
| 14 | - private String id; | |
| 17 | + private String path; | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg") | |
| 20 | + private String url; | |
| 15 | 21 | |
| 16 | - @ApiModelProperty(value = "文件类型", required = true, example = "jpg") | |
| 22 | + @ApiModelProperty(value = "文件类型", example = "jpg") | |
| 17 | 23 | private String type; |
| 18 | 24 | |
| 25 | + @ApiModelProperty(value = "文件大小", example = "2048", required = true) | |
| 26 | + private Integer size; | |
| 27 | + | |
| 19 | 28 | @ApiModelProperty(value = "创建时间", required = true) |
| 20 | 29 | private Date createTime; |
| 21 | 30 | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.infra.convert.file; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FileRespVO; | |
| 4 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; | |
| 5 | 5 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 6 | 6 | import org.mapstruct.Mapper; |
| 7 | 7 | import org.mapstruct.factory.Mappers; | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
| 1 | 1 | package cn.iocoder.yudao.module.infra.dal.dataobject.file; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | -import com.baomidou.mybatisplus.annotation.IdType; | |
| 5 | 4 | import com.baomidou.mybatisplus.annotation.TableField; |
| 6 | -import com.baomidou.mybatisplus.annotation.TableId; | |
| 7 | 5 | import com.baomidou.mybatisplus.annotation.TableName; |
| 8 | 6 | import lombok.*; |
| 9 | 7 | |
| ... | ... | @@ -27,8 +25,7 @@ public class FileDO extends BaseDO { |
| 27 | 25 | /** |
| 28 | 26 | * 编号,数据库自增 |
| 29 | 27 | */ |
| 30 | - @TableId(type = IdType.INPUT) | |
| 31 | - private String id; | |
| 28 | + private Long id; | |
| 32 | 29 | /** |
| 33 | 30 | * 配置编号 |
| 34 | 31 | * |
| ... | ... | @@ -40,6 +37,10 @@ public class FileDO extends BaseDO { |
| 40 | 37 | */ |
| 41 | 38 | private String path; |
| 42 | 39 | /** |
| 40 | + * 访问地址 | |
| 41 | + */ | |
| 42 | + private String url; | |
| 43 | + /** | |
| 43 | 44 | * 文件类型 |
| 44 | 45 | * |
| 45 | 46 | * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取 |
| ... | ... | @@ -47,17 +48,8 @@ public class FileDO extends BaseDO { |
| 47 | 48 | @TableField(value = "`type`") |
| 48 | 49 | private String type; |
| 49 | 50 | /** |
| 50 | - * 访问地址 | |
| 51 | - */ | |
| 52 | - private String url; | |
| 53 | - /** | |
| 54 | 51 | * 文件大小 |
| 55 | 52 | */ |
| 56 | 53 | private Integer size; |
| 57 | - /** | |
| 58 | - * 文件内容 | |
| 59 | - */ | |
| 60 | - @Deprecated | |
| 61 | - private byte[] content; | |
| 62 | 54 | |
| 63 | 55 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileContentDAOImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.file; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.file.core.client.db.DBFileContentFrameworkDAO; | |
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileContentDO; | |
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 6 | +import org.springframework.stereotype.Repository; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | + | |
| 10 | +@Repository | |
| 11 | +public class FileContentDAOImpl implements DBFileContentFrameworkDAO { | |
| 12 | + | |
| 13 | + @Resource | |
| 14 | + private FileContentMapper fileContentMapper; | |
| 15 | + | |
| 16 | + @Override | |
| 17 | + public void insert(Long configId, String path, byte[] content) { | |
| 18 | + FileContentDO entity = new FileContentDO().setConfigId(configId) | |
| 19 | + .setPath(path).setContent(content); | |
| 20 | + fileContentMapper.insert(entity); | |
| 21 | + } | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public void delete(Long configId, String path) { | |
| 25 | + fileContentMapper.delete(buildQuery(configId, path)); | |
| 26 | + } | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public byte[] selectContent(Long configId, String path) { | |
| 30 | + FileContentDO fileContentDO = fileContentMapper.selectOne( | |
| 31 | + buildQuery(configId, path).select(FileContentDO::getContent)); | |
| 32 | + return fileContentDO != null ? fileContentDO.getContent() : null; | |
| 33 | + } | |
| 34 | + | |
| 35 | + private LambdaQueryWrapper<FileContentDO> buildQuery(Long configId, String path) { | |
| 36 | + return new LambdaQueryWrapper<FileContentDO>() | |
| 37 | + .eq(FileContentDO::getConfigId, configId) | |
| 38 | + .eq(FileContentDO::getPath, path); | |
| 39 | + } | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileContentMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.file; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileContentDO; | |
| 4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
| 5 | +import org.apache.ibatis.annotations.Mapper; | |
| 6 | + | |
| 7 | +@Mapper | |
| 8 | +public interface FileContentMapper extends BaseMapper<FileContentDO> { | |
| 9 | +} | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
| ... | ... | @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.mysql.file; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; |
| 6 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | |
| 7 | 7 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 8 | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | |
| ... | ... | @@ -17,25 +17,10 @@ public interface FileMapper extends BaseMapperX<FileDO> { |
| 17 | 17 | |
| 18 | 18 | default PageResult<FileDO> selectPage(FilePageReqVO reqVO) { |
| 19 | 19 | return selectPage(reqVO, new QueryWrapperX<FileDO>() |
| 20 | - .likeIfPresent("id", reqVO.getId()) | |
| 20 | + .likeIfPresent("path", reqVO.getPath()) | |
| 21 | 21 | .likeIfPresent("type", reqVO.getType()) |
| 22 | 22 | .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) |
| 23 | 23 | .orderByDesc("create_time")); |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | - default Long selectCountById(String id) { | |
| 27 | - return selectCount(FileDO::getId, id); | |
| 28 | - } | |
| 29 | - | |
| 30 | - /** | |
| 31 | - * 基于 Path 获取文件 | |
| 32 | - * 实际上,是基于 ID 查询 | |
| 33 | - * | |
| 34 | - * @param path 路径 | |
| 35 | - * @return 文件 | |
| 36 | - */ | |
| 37 | - default FileDO selectByPath(String path) { | |
| 38 | - return selectById(path); | |
| 39 | - } | |
| 40 | - | |
| 41 | 26 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileConfiguration.java deleted
| 1 | -package cn.iocoder.yudao.module.infra.framework.file.config; | |
| 2 | - | |
| 3 | -import org.springframework.boot.context.properties.EnableConfigurationProperties; | |
| 4 | -import org.springframework.context.annotation.Configuration; | |
| 5 | - | |
| 6 | -/** | |
| 7 | - * 文件 配置类 | |
| 8 | - */ | |
| 9 | -@Configuration | |
| 10 | -@EnableConfigurationProperties(FileProperties.class) | |
| 11 | -public class FileConfiguration { | |
| 12 | -} |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileProperties.java deleted
| 1 | -package cn.iocoder.yudao.module.infra.framework.file.config; | |
| 2 | - | |
| 3 | -import lombok.Data; | |
| 4 | -import org.springframework.boot.context.properties.ConfigurationProperties; | |
| 5 | -import org.springframework.validation.annotation.Validated; | |
| 6 | - | |
| 7 | -import javax.validation.constraints.NotNull; | |
| 8 | - | |
| 9 | -@ConfigurationProperties(prefix = "yudao.file") | |
| 10 | -@Validated | |
| 11 | -@Data | |
| 12 | -public class FileProperties { | |
| 13 | - | |
| 14 | - /** | |
| 15 | - * 对应 FileController 的 getFile 方法 | |
| 16 | - */ | |
| 17 | - @NotNull(message = "基础文件路径不能为空") | |
| 18 | - private String basePath; | |
| 19 | - | |
| 20 | - // TODO 七牛、等等 | |
| 21 | - | |
| 22 | -} |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/package-info.java deleted
| 1 | -/** | |
| 2 | - * 文件的存储,推荐使用七牛、阿里云、华为云、腾讯云等文件服务 | |
| 3 | - * | |
| 4 | - * 在不采用云服务的情况下,我们有几种技术选型: | |
| 5 | - * 方案 1. 使用自建的文件服务,例如说 minIO、FastDFS 等等 | |
| 6 | - * 方案 2. 使用服务器的文件系统存储 | |
| 7 | - * 方案 3. 使用数据库进行存储 | |
| 8 | - * | |
| 9 | - * 如果考虑额外在搭建服务,推荐方案 1。 | |
| 10 | - * 对于方案 2 来说,如果要实现文件存储的高可用,需要多台服务器之间做实时同步,可以基于 rsync + inotify 来做 | |
| 11 | - * 对于方案 3 的话,实现起来最简单,但是数据库本身不适合存储海量的文件 | |
| 12 | - * | |
| 13 | - * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。 | |
| 14 | - * 随着文件的量级大了之后,还是推荐采用云服务。 | |
| 15 | - */ | |
| 16 | -package cn.iocoder.yudao.module.infra.framework.file; |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java
| ... | ... | @@ -36,7 +36,7 @@ public class SecurityConfiguration { |
| 36 | 36 | registry.antMatchers(adminSeverContextPath).anonymous() |
| 37 | 37 | .antMatchers(adminSeverContextPath + "/**").anonymous(); |
| 38 | 38 | // 文件的获取接口,可匿名访问 |
| 39 | - registry.antMatchers(buildAdminApi("/infra/file/get/**"), buildAppApi("/infra/file/get/**")).anonymous(); | |
| 39 | + registry.antMatchers(buildAdminApi("/infra/file/*/get/**"), buildAppApi("/infra/file/get/**")).permitAll(); | |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | }; | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java
| 1 | 1 | package cn.iocoder.yudao.module.infra.service.file; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.framework.file.core.client.FileClient; | |
| 4 | 5 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO; |
| 5 | 6 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO; |
| ... | ... | @@ -83,4 +84,19 @@ public interface FileConfigService { |
| 83 | 84 | */ |
| 84 | 85 | String testFileConfig(Long id); |
| 85 | 86 | |
| 87 | + /** | |
| 88 | + * 获得指定编号的文件客户端 | |
| 89 | + * | |
| 90 | + * @param id 配置编号 | |
| 91 | + * @return 文件客户端 | |
| 92 | + */ | |
| 93 | + FileClient getFileClient(Long id); | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * 获得 Master 文件客户端 | |
| 97 | + * | |
| 98 | + * @return 文件客户端 | |
| 99 | + */ | |
| 100 | + FileClient getMasterFileClient(); | |
| 101 | + | |
| 86 | 102 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
| ... | ... | @@ -233,4 +233,9 @@ public class FileConfigServiceImpl implements FileConfigService { |
| 233 | 233 | return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg"); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | + @Override | |
| 237 | + public FileClient getFileClient(Long id) { | |
| 238 | + return fileClientFactory.getFileClient(id); | |
| 239 | + } | |
| 240 | + | |
| 236 | 241 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
| 1 | 1 | package cn.iocoder.yudao.module.infra.service.file; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; | |
| 3 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 6 | 6 | |
| ... | ... | @@ -33,14 +33,15 @@ public interface FileService { |
| 33 | 33 | * |
| 34 | 34 | * @param id 编号 |
| 35 | 35 | */ |
| 36 | - void deleteFile(String id); | |
| 36 | + void deleteFile(Long id); | |
| 37 | 37 | |
| 38 | 38 | /** |
| 39 | - * 获得文件 | |
| 39 | + * 获得文件内容 | |
| 40 | 40 | * |
| 41 | + * @param configId 配置编号 | |
| 41 | 42 | * @param path 文件路径 |
| 42 | - * @return 文件 | |
| 43 | + * @return 文件内容 | |
| 43 | 44 | */ |
| 44 | - FileDO getFile(String path); | |
| 45 | + byte[] getFileContent(Long configId, String path); | |
| 45 | 46 | |
| 46 | 47 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.infra.service.file; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.io.FileTypeUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | |
| 4 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; | |
| 6 | +import cn.iocoder.yudao.framework.file.core.client.FileClient; | |
| 7 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | |
| 6 | 8 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 7 | 9 | import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; |
| 8 | -import cn.iocoder.yudao.module.infra.framework.file.config.FileProperties; | |
| 9 | 10 | import org.springframework.stereotype.Service; |
| 10 | 11 | |
| 11 | 12 | import javax.annotation.Resource; |
| 12 | 13 | import java.io.ByteArrayInputStream; |
| 13 | 14 | |
| 14 | 15 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 15 | -import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 16 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; | |
| 16 | 17 | |
| 17 | 18 | /** |
| 18 | 19 | * 文件 Service 实现类 |
| ... | ... | @@ -23,10 +24,10 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; |
| 23 | 24 | public class FileServiceImpl implements FileService { |
| 24 | 25 | |
| 25 | 26 | @Resource |
| 26 | - private FileMapper fileMapper; | |
| 27 | + private FileConfigService fileConfigService; | |
| 27 | 28 | |
| 28 | 29 | @Resource |
| 29 | - private FileProperties fileProperties; | |
| 30 | + private FileMapper fileMapper; | |
| 30 | 31 | |
| 31 | 32 | @Override |
| 32 | 33 | public PageResult<FileDO> getFilePage(FilePageReqVO pageReqVO) { |
| ... | ... | @@ -35,36 +36,49 @@ public class FileServiceImpl implements FileService { |
| 35 | 36 | |
| 36 | 37 | @Override |
| 37 | 38 | public String createFile(String path, byte[] content) { |
| 38 | - if (fileMapper.selectCountById(path) > 0) { | |
| 39 | - throw exception(FILE_PATH_EXISTS); | |
| 40 | - } | |
| 39 | + // 上传到文件存储器 | |
| 40 | + FileClient client = fileConfigService.getMasterFileClient(); | |
| 41 | + Assert.notNull(client, "客户端(master) 不能为空"); | |
| 42 | + String url = client.upload(content, path); | |
| 43 | + | |
| 41 | 44 | // 保存到数据库 |
| 42 | 45 | FileDO file = new FileDO(); |
| 43 | - file.setId(path); | |
| 46 | + file.setConfigId(client.getId()); | |
| 47 | + file.setPath(path); | |
| 48 | + file.setUrl(url); | |
| 44 | 49 | file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content))); |
| 45 | - file.setContent(content); | |
| 50 | + file.setSize(content.length); | |
| 46 | 51 | fileMapper.insert(file); |
| 47 | - // 拼接路径返回 | |
| 48 | - return fileProperties.getBasePath() + path; | |
| 52 | + return url; | |
| 49 | 53 | } |
| 50 | 54 | |
| 51 | 55 | @Override |
| 52 | - public void deleteFile(String id) { | |
| 56 | + public void deleteFile(Long id) { | |
| 53 | 57 | // 校验存在 |
| 54 | - this.validateFileExists(id); | |
| 55 | - // 更新 | |
| 58 | + FileDO file = this.validateFileExists(id); | |
| 59 | + | |
| 60 | + // 从文件存储器中删除 | |
| 61 | + FileClient client = fileConfigService.getFileClient(file.getConfigId()); | |
| 62 | + Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId()); | |
| 63 | + client.delete(file.getPath()); | |
| 64 | + | |
| 65 | + // 删除记录 | |
| 56 | 66 | fileMapper.deleteById(id); |
| 57 | 67 | } |
| 58 | 68 | |
| 59 | - private void validateFileExists(String id) { | |
| 60 | - if (fileMapper.selectById(id) == null) { | |
| 69 | + private FileDO validateFileExists(Long id) { | |
| 70 | + FileDO fileDO = fileMapper.selectById(id); | |
| 71 | + if (fileDO == null) { | |
| 61 | 72 | throw exception(FILE_NOT_EXISTS); |
| 62 | 73 | } |
| 74 | + return fileDO; | |
| 63 | 75 | } |
| 64 | 76 | |
| 65 | 77 | @Override |
| 66 | - public FileDO getFile(String path) { | |
| 67 | - return fileMapper.selectByPath(path); | |
| 78 | + public byte[] getFileContent(Long configId, String path) { | |
| 79 | + FileClient client = fileConfigService.getFileClient(configId); | |
| 80 | + Assert.notNull(client, "客户端({}) 不能为空", configId); | |
| 81 | + return client.getContent(path); | |
| 68 | 82 | } |
| 69 | 83 | |
| 70 | 84 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
| ... | ... | @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.infra.service.file; |
| 3 | 3 | import cn.hutool.core.io.resource.ResourceUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 6 | +import cn.iocoder.yudao.framework.file.core.client.FileClient; | |
| 6 | 7 | import cn.iocoder.yudao.framework.test.core.util.AssertUtils; |
| 7 | -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; | |
| 8 | +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | |
| 8 | 9 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; |
| 9 | 10 | import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; |
| 10 | -import cn.iocoder.yudao.module.infra.framework.file.config.FileProperties; | |
| 11 | 11 | import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; |
| 12 | 12 | import org.junit.jupiter.api.Test; |
| 13 | 13 | import org.springframework.boot.test.mock.mockito.MockBean; |
| ... | ... | @@ -17,47 +17,46 @@ import javax.annotation.Resource; |
| 17 | 17 | |
| 18 | 18 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; |
| 19 | 19 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 20 | -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 21 | -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | |
| 20 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 22 | 21 | import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; |
| 23 | 22 | import static org.junit.jupiter.api.Assertions.*; |
| 23 | +import static org.mockito.ArgumentMatchers.same; | |
| 24 | +import static org.mockito.Mockito.*; | |
| 24 | 25 | |
| 25 | -@Import({FileServiceImpl.class, FileProperties.class}) | |
| 26 | +@Import({FileServiceImpl.class}) | |
| 26 | 27 | public class FileServiceTest extends BaseDbUnitTest { |
| 27 | 28 | |
| 28 | 29 | @Resource |
| 29 | 30 | private FileService fileService; |
| 30 | 31 | |
| 31 | - @MockBean | |
| 32 | - private FileProperties fileProperties; | |
| 33 | - | |
| 34 | 32 | @Resource |
| 35 | 33 | private FileMapper fileMapper; |
| 36 | 34 | |
| 35 | + @MockBean | |
| 36 | + private FileConfigService fileConfigService; | |
| 37 | + | |
| 37 | 38 | @Test |
| 38 | 39 | public void testGetFilePage() { |
| 39 | 40 | // mock 数据 |
| 40 | 41 | FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到 |
| 41 | - o.setId("yunai"); | |
| 42 | + o.setPath("yunai"); | |
| 42 | 43 | o.setType("jpg"); |
| 43 | 44 | o.setCreateTime(buildTime(2021, 1, 15)); |
| 44 | 45 | }); |
| 45 | 46 | fileMapper.insert(dbFile); |
| 46 | - // 测试 id 不匹配 | |
| 47 | - fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setId("tudou"))); | |
| 47 | + // 测试 path 不匹配 | |
| 48 | + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou"))); | |
| 48 | 49 | // 测试 type 不匹配 |
| 49 | 50 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { |
| 50 | - o.setId("yunai02"); | |
| 51 | 51 | o.setType("png"); |
| 52 | 52 | })); |
| 53 | 53 | // 测试 createTime 不匹配 |
| 54 | 54 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { |
| 55 | - o.setId("yunai03"); | |
| 56 | 55 | o.setCreateTime(buildTime(2020, 1, 15)); |
| 57 | 56 | })); |
| 58 | 57 | // 准备参数 |
| 59 | 58 | FilePageReqVO reqVO = new FilePageReqVO(); |
| 60 | - reqVO.setId("yunai"); | |
| 59 | + reqVO.setPath("yunai"); | |
| 61 | 60 | reqVO.setType("jp"); |
| 62 | 61 | reqVO.setBeginCreateTime(buildTime(2021, 1, 10)); |
| 63 | 62 | reqVO.setEndCreateTime(buildTime(2021, 1, 20)); |
| ... | ... | @@ -67,7 +66,7 @@ public class FileServiceTest extends BaseDbUnitTest { |
| 67 | 66 | // 断言 |
| 68 | 67 | assertEquals(1, pageResult.getTotal()); |
| 69 | 68 | assertEquals(1, pageResult.getList().size()); |
| 70 | - AssertUtils.assertPojoEquals(dbFile, pageResult.getList().get(0), "content"); | |
| 69 | + AssertUtils.assertPojoEquals(dbFile, pageResult.getList().get(0)); | |
| 71 | 70 | } |
| 72 | 71 | |
| 73 | 72 | @Test |
| ... | ... | @@ -75,52 +74,68 @@ public class FileServiceTest extends BaseDbUnitTest { |
| 75 | 74 | // 准备参数 |
| 76 | 75 | String path = randomString(); |
| 77 | 76 | byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); |
| 77 | + // mock Master 文件客户端 | |
| 78 | + FileClient client = mock(FileClient.class); | |
| 79 | + when(fileConfigService.getMasterFileClient()).thenReturn(client); | |
| 80 | + String url = randomString(); | |
| 81 | + when(client.upload(same(content), same(path))).thenReturn(url); | |
| 82 | + when(client.getId()).thenReturn(10L); | |
| 78 | 83 | |
| 79 | 84 | // 调用 |
| 80 | - String url = fileService.createFile(path, content); | |
| 85 | + String result = fileService.createFile(path, content); | |
| 81 | 86 | // 断言 |
| 82 | - assertEquals(fileProperties.getBasePath() + path, url); | |
| 87 | + assertEquals(result, url); | |
| 83 | 88 | // 校验数据 |
| 84 | - FileDO file = fileMapper.selectById(path); | |
| 85 | - assertEquals(path, file.getId()); | |
| 89 | + FileDO file = fileMapper.selectOne(FileDO::getPath, path); | |
| 90 | + assertEquals(10L, file.getConfigId()); | |
| 91 | + assertEquals(path, file.getPath()); | |
| 92 | + assertEquals(url, file.getUrl()); | |
| 86 | 93 | assertEquals("jpg", file.getType()); |
| 87 | - assertArrayEquals(content, file.getContent()); | |
| 88 | - } | |
| 89 | - | |
| 90 | - @Test | |
| 91 | - public void testCreateFile_exists() { | |
| 92 | - // mock 数据 | |
| 93 | - FileDO dbFile = randomPojo(FileDO.class); | |
| 94 | - fileMapper.insert(dbFile); | |
| 95 | - // 准备参数 | |
| 96 | - String path = dbFile.getId(); // 模拟已存在 | |
| 97 | - byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); | |
| 98 | - | |
| 99 | - // 调用,并断言异常 | |
| 100 | - assertServiceException(() -> fileService.createFile(path, content), FILE_PATH_EXISTS); | |
| 94 | + assertEquals(content.length, file.getSize()); | |
| 101 | 95 | } |
| 102 | 96 | |
| 103 | 97 | @Test |
| 104 | 98 | public void testDeleteFile_success() { |
| 105 | 99 | // mock 数据 |
| 106 | - FileDO dbFile = randomPojo(FileDO.class); | |
| 100 | + FileDO dbFile = randomPojo(FileDO.class, o -> o.setConfigId(10L).setPath("tudou.jpg")); | |
| 107 | 101 | fileMapper.insert(dbFile);// @Sql: 先插入出一条存在的数据 |
| 102 | + // mock Master 文件客户端 | |
| 103 | + FileClient client = mock(FileClient.class); | |
| 104 | + when(fileConfigService.getFileClient(eq(10L))).thenReturn(client); | |
| 108 | 105 | // 准备参数 |
| 109 | - String id = dbFile.getId(); | |
| 106 | + Long id = dbFile.getId(); | |
| 110 | 107 | |
| 111 | 108 | // 调用 |
| 112 | 109 | fileService.deleteFile(id); |
| 113 | 110 | // 校验数据不存在了 |
| 114 | 111 | assertNull(fileMapper.selectById(id)); |
| 112 | + // 校验调用 | |
| 113 | + verify(client).delete(eq("tudou.jpg")); | |
| 115 | 114 | } |
| 116 | 115 | |
| 117 | 116 | @Test |
| 118 | 117 | public void testDeleteFile_notExists() { |
| 119 | 118 | // 准备参数 |
| 120 | - String id = randomString(); | |
| 119 | + Long id = randomLongId(); | |
| 121 | 120 | |
| 122 | 121 | // 调用, 并断言异常 |
| 123 | 122 | assertServiceException(() -> fileService.deleteFile(id), FILE_NOT_EXISTS); |
| 124 | 123 | } |
| 125 | 124 | |
| 125 | + @Test | |
| 126 | + public void testGetFileContent() { | |
| 127 | + // 准备参数 | |
| 128 | + Long configId = 10L; | |
| 129 | + String path = "tudou.jpg"; | |
| 130 | + // mock 方法 | |
| 131 | + FileClient client = mock(FileClient.class); | |
| 132 | + when(fileConfigService.getFileClient(eq(10L))).thenReturn(client); | |
| 133 | + byte[] content = new byte[]{}; | |
| 134 | + when(client.getContent(eq("tudou.jpg"))).thenReturn(content); | |
| 135 | + | |
| 136 | + // 调用 | |
| 137 | + byte[] result = fileService.getFileContent(configId, path); | |
| 138 | + // 断言 | |
| 139 | + assertSame(result, content); | |
| 140 | + } | |
| 126 | 141 | } | ... | ... |
yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -32,9 +32,12 @@ CREATE TABLE IF NOT EXISTS "infra_file_config" ( |
| 32 | 32 | ) COMMENT '文件配置表'; |
| 33 | 33 | |
| 34 | 34 | CREATE TABLE IF NOT EXISTS "infra_file" ( |
| 35 | - "id" varchar(188) NOT NULL, | |
| 35 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 36 | + "config_id" bigint NOT NULL, | |
| 37 | + "path" varchar(512), | |
| 38 | + "url" varchar(1024), | |
| 36 | 39 | "type" varchar(63) DEFAULT NULL, |
| 37 | - "content" blob NOT NULL, | |
| 40 | + "size" bigint NOT NULL, | |
| 38 | 41 | "creator" varchar(64) DEFAULT '', |
| 39 | 42 | "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 40 | 43 | "updater" varchar(64) DEFAULT '', | ... | ... |
yudao-server/src/main/resources/application-dev.yaml
| ... | ... | @@ -172,8 +172,6 @@ yudao: |
| 172 | 172 | session-timeout: 30m |
| 173 | 173 | mock-enable: true |
| 174 | 174 | mock-secret: test |
| 175 | - file: | |
| 176 | - base-path: http://api-dashboard.yudao.iocoder.cn${yudao.web.admin-api.prefix}/infra/file/get/ | |
| 177 | 175 | xss: |
| 178 | 176 | enable: false |
| 179 | 177 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | ... | ... |
yudao-server/src/main/resources/application-local.yaml
| ... | ... | @@ -184,8 +184,6 @@ yudao: |
| 184 | 184 | session-timeout: 1d |
| 185 | 185 | mock-enable: true |
| 186 | 186 | mock-secret: test |
| 187 | - file: | |
| 188 | - base-path: http://127.0.0.1:${server.port}${yudao.web.admin-api.prefix}/infra/file/get/ | |
| 189 | 187 | xss: |
| 190 | 188 | enable: false |
| 191 | 189 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -92,7 +92,7 @@ yudao: |
| 92 | 92 | ignore-urls: |
| 93 | 93 | - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 |
| 94 | 94 | - /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关 |
| 95 | - - /admin-api/infra/file/get/* # 获取图片,和租户无关 | |
| 95 | + - /admin-api/infra/file/*/get/** # 获取图片,和租户无关 | |
| 96 | 96 | - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 |
| 97 | 97 | ignore-tables: |
| 98 | 98 | - system_tenant | ... | ... |
yudao-ui-admin/src/views/infra/file/index.vue
| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | |
| 4 | 4 | <!-- 搜索工作栏 --> |
| 5 | 5 | <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px"> |
| 6 | - <el-form-item label="文件路径" prop="id"> | |
| 7 | - <el-input v-model="queryParams.id" placeholder="请输入文件路径" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 6 | + <el-form-item label="文件路径" prop="path"> | |
| 7 | + <el-input v-model="queryParams.path" placeholder="请输入文件路径" clearable size="small" @keyup.enter.native="handleQuery"/> | |
| 8 | 8 | </el-form-item> |
| 9 | 9 | <el-form-item label="文件类型" prop="type"> |
| 10 | 10 | <el-select v-model="queryParams.type" placeholder="请选择文件类型" clearable size="small"> |
| ... | ... | @@ -31,21 +31,23 @@ |
| 31 | 31 | |
| 32 | 32 | <!-- 列表 --> |
| 33 | 33 | <el-table v-loading="loading" :data="list"> |
| 34 | - <el-table-column label="文件路径" align="center" prop="id" width="300" /> | |
| 34 | + <el-table-column label="文件名" align="center" prop="path" /> | |
| 35 | + <el-table-column label="URL" align="center" prop="url" /> | |
| 36 | + <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" /> | |
| 35 | 37 | <el-table-column label="文件类型" align="center" prop="type" width="80" /> |
| 36 | - <el-table-column label="文件内容" align="center" prop="content"> | |
| 37 | - <template slot-scope="scope"> | |
| 38 | - <img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'" | |
| 39 | - width="200px" :src="getFileUrl + scope.row.id"> | |
| 40 | - <i v-else>非图片,无法预览</i> | |
| 41 | - </template> | |
| 42 | - </el-table-column> | |
| 43 | - <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | |
| 38 | +<!-- <el-table-column label="文件内容" align="center" prop="content">--> | |
| 39 | +<!-- <template slot-scope="scope">--> | |
| 40 | +<!-- <img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'"--> | |
| 41 | +<!-- width="200px" :src="getFileUrl + scope.row.id">--> | |
| 42 | +<!-- <i v-else>非图片,无法预览</i>--> | |
| 43 | +<!-- </template>--> | |
| 44 | +<!-- </el-table-column>--> | |
| 45 | + <el-table-column label="上传时间" align="center" prop="createTime" width="180"> | |
| 44 | 46 | <template slot-scope="scope"> |
| 45 | 47 | <span>{{ parseTime(scope.row.createTime) }}</span> |
| 46 | 48 | </template> |
| 47 | 49 | </el-table-column> |
| 48 | - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | |
| 50 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100"> | |
| 49 | 51 | <template slot-scope="scope"> |
| 50 | 52 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" |
| 51 | 53 | v-hasPermi="['infra:file:delete']">删除</el-button> |
| ... | ... | @@ -102,7 +104,7 @@ export default { |
| 102 | 104 | queryParams: { |
| 103 | 105 | pageNo: 1, |
| 104 | 106 | pageSize: 10, |
| 105 | - id: null, | |
| 107 | + path: null, | |
| 106 | 108 | type: null, |
| 107 | 109 | }, |
| 108 | 110 | // 用户导入参数 |
| ... | ... | @@ -193,6 +195,15 @@ export default { |
| 193 | 195 | this.$modal.msgSuccess("删除成功"); |
| 194 | 196 | }).catch(() => {}); |
| 195 | 197 | }, |
| 198 | + // 用户昵称展示 | |
| 199 | + sizeFormat(row, column) { | |
| 200 | + const unitArr = ["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"]; | |
| 201 | + const srcSize = parseFloat(row.size); | |
| 202 | + const index = Math.floor(Math.log(srcSize) / Math.log(1024)); | |
| 203 | + let size =srcSize/Math.pow(1024,index); | |
| 204 | + size = size.toFixed(2);//保留的小数位数 | |
| 205 | + return size + ' ' + unitArr[index]; | |
| 206 | + }, | |
| 196 | 207 | } |
| 197 | 208 | }; |
| 198 | 209 | </script> | ... | ... |