Commit 36d7775171d3fdc381414b84a450db93cafa92ef

Authored by jiangqiang
1 parent d14ad888

1. 修改文件名和文件路径字段长度一致,因为如果不存在文件名的情况下,会使用文件路径作为字段名,防止数据库报错字段内容太长。

2. 修改type字段为ext_name,因为此字段本来就存的文件扩展名,并且新增mime_type字段,用来存储文件的类型。方便后期拓展网盘项目。
3. 修改文件路径生成方式:之前是md5,现在是sha256,降低文件碰撞概率。方便拓展网盘项目,实现秒传等功能。
sql/mysql/ruoyi-vue-pro.sql
... ... @@ -689,10 +689,11 @@ DROP TABLE IF EXISTS `infra_file`;
689 689 CREATE TABLE `infra_file` (
690 690 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号',
691 691 `config_id` bigint NULL DEFAULT NULL COMMENT '配置编号',
692   - `name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名',
  692 + `name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名',
693 693 `path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件路径',
694 694 `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件 URL',
695   - `type` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件类型',
  695 + `ext_name` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件扩展名',
  696 + `mime_type` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件MIME类型',
696 697 `size` int NOT NULL COMMENT '文件大小',
697 698 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
698 699 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
... ...
sql/oracle/ruoyi-vue-pro.sql
... ... @@ -878,7 +878,8 @@ CREATE TABLE "INFRA_FILE" (
878 878 "CONFIG_ID" NUMBER(20,0),
879 879 "PATH" NVARCHAR2(512),
880 880 "URL" NCLOB,
881   - "TYPE" NVARCHAR2(63),
  881 + "EXT_NAME" NVARCHAR2(63),
  882 + "MIME_TYPE" NVARCHAR2(63),
882 883 "SIZE" NUMBER(11,0) NOT NULL,
883 884 "CREATOR" NVARCHAR2(64),
884 885 "CREATE_TIME" DATE NOT NULL,
... ... @@ -908,7 +909,8 @@ COMMENT ON COLUMN "INFRA_FILE"."ID" IS '文件编号';
908 909 COMMENT ON COLUMN "INFRA_FILE"."CONFIG_ID" IS '配置编号';
909 910 COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径';
910 911 COMMENT ON COLUMN "INFRA_FILE"."URL" IS '文件 URL';
911   -COMMENT ON COLUMN "INFRA_FILE"."TYPE" IS '文件类型';
  912 +COMMENT ON COLUMN "INFRA_FILE"."EXT_NAME" IS '文件扩展名';
  913 +COMMENT ON COLUMN "INFRA_FILE"."MIME_TYPE" IS '文件MIME类型';
912 914 COMMENT ON COLUMN "INFRA_FILE"."SIZE" IS '文件大小';
913 915 COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者';
914 916 COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间';
... ...
sql/postgresql/ruoyi-vue-pro.sql
... ... @@ -1717,21 +1717,23 @@ CREATE TABLE "infra_file" (
1717 1717 "config_id" int8,
1718 1718 "path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
1719 1719 "url" varchar(1024) COLLATE "pg_catalog"."default" NOT NULL,
1720   - "type" varchar(63) COLLATE "pg_catalog"."default",
  1720 + "ext_name" varchar(63) COLLATE "pg_catalog"."default",
  1721 + "mime_type" varchar(63) COLLATE "pg_catalog"."default",
1721 1722 "size" int4 NOT NULL,
1722 1723 "creator" varchar(64) COLLATE "pg_catalog"."default",
1723 1724 "create_time" timestamp(6) NOT NULL,
1724 1725 "updater" varchar(64) COLLATE "pg_catalog"."default",
1725 1726 "update_time" timestamp(6) NOT NULL,
1726 1727 "deleted" int2 NOT NULL DEFAULT 0,
1727   - "name" varchar(255) COLLATE "pg_catalog"."default"
  1728 + "name" varchar(512) COLLATE "pg_catalog"."default"
1728 1729 )
1729 1730 ;
1730 1731 COMMENT ON COLUMN "infra_file"."id" IS '文件编号';
1731 1732 COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号';
1732 1733 COMMENT ON COLUMN "infra_file"."path" IS '文件路径';
1733 1734 COMMENT ON COLUMN "infra_file"."url" IS '文件 URL';
1734   -COMMENT ON COLUMN "infra_file"."type" IS '文件类型';
  1735 +COMMENT ON COLUMN "infra_file"."ext_name" IS '文件扩展名';
  1736 +COMMENT ON COLUMN "infra_file"."mime_type" IS '文件MIME类型';
1735 1737 COMMENT ON COLUMN "infra_file"."size" IS '文件大小';
1736 1738 COMMENT ON COLUMN "infra_file"."creator" IS '创建者';
1737 1739 COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间';
... ...
sql/sqlserver/ruoyi-vue-pro.sql
... ... @@ -2634,14 +2634,15 @@ CREATE TABLE [dbo].[infra_file] (
2634 2634 [config_id] bigint NULL,
2635 2635 [path] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
2636 2636 [url] nvarchar(1024) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
2637   - [type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  2637 + [ext_name] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
  2638 + [mime_type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
2638 2639 [size] int NOT NULL,
2639 2640 [creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
2640 2641 [create_time] datetime2(7) NOT NULL,
2641 2642 [updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
2642 2643 [update_time] datetime2(7) NOT NULL,
2643 2644 [deleted] bit DEFAULT 0 NOT NULL,
2644   - [name] nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
  2645 + [name] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
2645 2646 )
2646 2647 GO
2647 2648  
... ... @@ -2677,10 +2678,17 @@ EXEC sp_addextendedproperty
2677 2678 GO
2678 2679  
2679 2680 EXEC sp_addextendedproperty
2680   -'MS_Description', N'文件类型',
  2681 +'MS_Description', N'文件扩展名',
2681 2682 'SCHEMA', N'dbo',
2682 2683 'TABLE', N'infra_file',
2683   -'COLUMN', N'type'
  2684 +'COLUMN', N'ext_name'
  2685 +GO
  2686 +
  2687 +EXEC sp_addextendedproperty
  2688 +'MS_Description', N'文件MIME类型',
  2689 +'SCHEMA', N'dbo',
  2690 +'TABLE', N'infra_file',
  2691 +'COLUMN', N'mime_type'
2684 2692 GO
2685 2693  
2686 2694 EXEC sp_addextendedproperty
... ...
yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
... ... @@ -14,7 +14,7 @@ public interface FileApi {
14 14 * @return 文件路径
15 15 */
16 16 default String createFile(byte[] content) {
17   - return createFile(null, null, content);
  17 + return createFile(null, null, "application/octet-stream", content);
18 18 }
19 19  
20 20 /**
... ... @@ -25,17 +25,18 @@ public interface FileApi {
25 25 * @return 文件路径
26 26 */
27 27 default String createFile(String path, byte[] content) {
28   - return createFile(null, path, content);
  28 + return createFile(null, path, "application/octet-stream", content);
29 29 }
30 30  
31 31 /**
32 32 * 保存文件,并返回文件的访问路径
33 33 *
34   - * @param name 文件名称
35   - * @param path 文件路径
36   - * @param content 文件内容
  34 + * @param name 文件名称
  35 + * @param path 文件路径
  36 + * @param mimeType 文件类型
  37 + * @param content 文件内容
37 38 * @return 文件路径
38 39 */
39   - String createFile(String name, String path, byte[] content);
  40 + String createFile(String name, String path, String mimeType, byte[] content);
40 41  
41 42 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
... ... @@ -19,8 +19,8 @@ public class FileApiImpl implements FileApi {
19 19 private FileService fileService;
20 20  
21 21 @Override
22   - public String createFile(String name, String path, byte[] content) {
23   - return fileService.createFile(name, path, content);
  22 + public String createFile(String name, String path, String mimeType, byte[] content) {
  23 + return fileService.createFile(name, path, mimeType, content);
24 24 }
25 25  
26 26 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
... ... @@ -46,7 +46,7 @@ public class FileController {
46 46 @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
47 47 public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
48 48 @RequestParam(value = "path", required = false) String path) throws Exception {
49   - return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
  49 + return success(fileService.createFile(file.getOriginalFilename(), path, file.getContentType(), IoUtil.readBytes(file.getInputStream())));
50 50 }
51 51  
52 52 @DeleteMapping("/delete")
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
... ... @@ -38,7 +38,7 @@ public class FileDO extends BaseDO {
38 38 */
39 39 private String name;
40 40 /**
41   - * 路径,即文件名
  41 + * 路径,即文件名,唯一不可重复
42 42 */
43 43 private String path;
44 44 /**
... ... @@ -46,11 +46,15 @@ public class FileDO extends BaseDO {
46 46 */
47 47 private String url;
48 48 /**
49   - * 文件类型
50   - *
  49 + * 文件扩展名
  50 + * <p>
51 51 * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
52 52 */
53   - private String type;
  53 + private String extName;
  54 + /**
  55 + * 文件的MIME类型,默认为"application/octet-stream"
  56 + */
  57 + private String mimeType;
54 58 /**
55 59 * 文件大小
56 60 */
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
... ... @@ -18,7 +18,7 @@ public interface FileMapper extends BaseMapperX&lt;FileDO&gt; {
18 18 default PageResult<FileDO> selectPage(FilePageReqVO reqVO) {
19 19 return selectPage(reqVO, new LambdaQueryWrapperX<FileDO>()
20 20 .likeIfPresent(FileDO::getPath, reqVO.getPath())
21   - .likeIfPresent(FileDO::getType, reqVO.getType())
  21 + .likeIfPresent(FileDO::getExtName, reqVO.getType())
22 22 .betweenIfPresent(FileDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
23 23 .orderByDesc(FileDO::getId));
24 24 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
... ... @@ -24,10 +24,11 @@ public interface FileService {
24 24 *
25 25 * @param name 文件名称
26 26 * @param path 文件路径
  27 + * @param mimeType 文件MIME类型
27 28 * @param content 文件内容
28 29 * @return 文件路径
29 30 */
30   - String createFile(String name, String path, byte[] content);
  31 + String createFile(String name, String path, String mimeType,byte[] content);
31 32  
32 33 /**
33 34 * 删除文件
... ...
yudao-module-infra/yudao-module-infra-biz/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.io.file.FileNameUtil;
4 5 import cn.hutool.core.lang.Assert;
5 6 import cn.hutool.core.util.StrUtil;
6 7 import cn.hutool.crypto.digest.DigestUtil;
... ... @@ -39,11 +40,13 @@ public class FileServiceImpl implements FileService {
39 40  
40 41 @Override
41 42 @SneakyThrows
42   - public String createFile(String name, String path, byte[] content) {
43   - // 计算默认的 path 名
44   - String type = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
  43 + public String createFile(String name, String path, String mimeType, byte[] content) {
  44 + //获取文件的真实扩展名
  45 + String extName = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
  46 + FileNameUtil.extName(name);
45 47 if (StrUtil.isEmpty(path)) {
46   - path = DigestUtil.md5Hex(content) + '.' + type;
  48 + //使用sha256计算文件都唯一路径,降低碰撞概率
  49 + path = DigestUtil.sha256Hex(content) + '.' + extName;
47 50 }
48 51 // 如果 name 为空,则使用 path 填充
49 52 if (StrUtil.isEmpty(name)) {
... ... @@ -61,7 +64,8 @@ public class FileServiceImpl implements FileService {
61 64 file.setName(name);
62 65 file.setPath(path);
63 66 file.setUrl(url);
64   - file.setType(type);
  67 + file.setExtName(extName);
  68 + file.setMimeType(mimeType);
65 69 file.setSize(content.length);
66 70 fileMapper.insert(file);
67 71 return url;
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
... ... @@ -40,7 +40,7 @@ public class FileServiceTest extends BaseDbUnitTest {
40 40 // mock 数据
41 41 FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
42 42 o.setPath("yunai");
43   - o.setType("jpg");
  43 + o.setExtName("jpg");
44 44 o.setCreateTime(buildTime(2021, 1, 15));
45 45 });
46 46 fileMapper.insert(dbFile);
... ... @@ -48,7 +48,7 @@ public class FileServiceTest extends BaseDbUnitTest {
48 48 fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
49 49 // 测试 type 不匹配
50 50 fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
51   - o.setType("png");
  51 + o.setExtName("png");
52 52 }));
53 53 // 测试 createTime 不匹配
54 54 fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
... ... @@ -82,7 +82,7 @@ public class FileServiceTest extends BaseDbUnitTest {
82 82 when(client.getId()).thenReturn(10L);
83 83 String name = "单测文件名";
84 84 // 调用
85   - String result = fileService.createFile(name, path, content);
  85 + String result = fileService.createFile(name, path, "application/octet-stream", content);
86 86 // 断言
87 87 assertEquals(result, url);
88 88 // 校验数据
... ... @@ -90,7 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest {
90 90 assertEquals(10L, file.getConfigId());
91 91 assertEquals(path, file.getPath());
92 92 assertEquals(url, file.getUrl());
93   - assertEquals("jpg", file.getType());
  93 + assertEquals("jpg", file.getExtName());
94 94 assertEquals(content.length, file.getSize());
95 95 }
96 96  
... ...