Browse Source

1. 修改文件名和文件路径字段长度一致,因为如果不存在文件名的情况下,会使用文件路径作为字段名,防止数据库报错字段内容太长。
2. 修改type字段为ext_name,因为此字段本来就存的文件扩展名,并且新增mime_type字段,用来存储文件的类型。方便后期拓展网盘项目。
3. 修改文件路径生成方式:之前是md5,现在是sha256,降低文件碰撞概率。方便拓展网盘项目,实现秒传等功能。

jiangqiang 2 years ago
parent
commit
36d7775171

+ 3 - 2
sql/mysql/ruoyi-vue-pro.sql

@@ -689,10 +689,11 @@ DROP TABLE IF EXISTS `infra_file`;
 CREATE TABLE `infra_file`  (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号',
   `config_id` bigint NULL DEFAULT NULL COMMENT '配置编号',
-  `name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名',
+  `name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名',
   `path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件路径',
   `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件 URL',
-  `type` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件类型',
+  `ext_name` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件扩展名',
+  `mime_type` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件MIME类型',
   `size` int NOT NULL COMMENT '文件大小',
   `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
   `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

+ 4 - 2
sql/oracle/ruoyi-vue-pro.sql

@@ -878,7 +878,8 @@ CREATE TABLE "INFRA_FILE" (
   "CONFIG_ID" NUMBER(20,0),
   "PATH" NVARCHAR2(512),
   "URL" NCLOB,
-  "TYPE" NVARCHAR2(63),
+  "EXT_NAME" NVARCHAR2(63),
+  "MIME_TYPE" NVARCHAR2(63),
   "SIZE" NUMBER(11,0) NOT NULL,
   "CREATOR" NVARCHAR2(64),
   "CREATE_TIME" DATE NOT NULL,
@@ -908,7 +909,8 @@ COMMENT ON COLUMN "INFRA_FILE"."ID" IS '文件编号';
 COMMENT ON COLUMN "INFRA_FILE"."CONFIG_ID" IS '配置编号';
 COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径';
 COMMENT ON COLUMN "INFRA_FILE"."URL" IS '文件 URL';
-COMMENT ON COLUMN "INFRA_FILE"."TYPE" IS '文件类型';
+COMMENT ON COLUMN "INFRA_FILE"."EXT_NAME" IS '文件扩展名';
+COMMENT ON COLUMN "INFRA_FILE"."MIME_TYPE" IS '文件MIME类型';
 COMMENT ON COLUMN "INFRA_FILE"."SIZE" IS '文件大小';
 COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者';
 COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间';

+ 5 - 3
sql/postgresql/ruoyi-vue-pro.sql

@@ -1717,21 +1717,23 @@ CREATE TABLE "infra_file" (
   "config_id" int8,
   "path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
   "url" varchar(1024) COLLATE "pg_catalog"."default" NOT NULL,
-  "type" varchar(63) COLLATE "pg_catalog"."default",
+  "ext_name" varchar(63) COLLATE "pg_catalog"."default",
+  "mime_type" varchar(63) COLLATE "pg_catalog"."default",
   "size" int4 NOT NULL,
   "creator" varchar(64) COLLATE "pg_catalog"."default",
   "create_time" timestamp(6) NOT NULL,
   "updater" varchar(64) COLLATE "pg_catalog"."default",
   "update_time" timestamp(6) NOT NULL,
   "deleted" int2 NOT NULL DEFAULT 0,
-  "name" varchar(255) COLLATE "pg_catalog"."default"
+  "name" varchar(512) COLLATE "pg_catalog"."default"
 )
 ;
 COMMENT ON COLUMN "infra_file"."id" IS '文件编号';
 COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号';
 COMMENT ON COLUMN "infra_file"."path" IS '文件路径';
 COMMENT ON COLUMN "infra_file"."url" IS '文件 URL';
-COMMENT ON COLUMN "infra_file"."type" IS '文件类型';
+COMMENT ON COLUMN "infra_file"."ext_name" IS '文件扩展名';
+COMMENT ON COLUMN "infra_file"."mime_type" IS '文件MIME类型';
 COMMENT ON COLUMN "infra_file"."size" IS '文件大小';
 COMMENT ON COLUMN "infra_file"."creator" IS '创建者';
 COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间';

+ 12 - 4
sql/sqlserver/ruoyi-vue-pro.sql

@@ -2634,14 +2634,15 @@ CREATE TABLE [dbo].[infra_file] (
   [config_id] bigint  NULL,
   [path] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT NULL,
   [url] nvarchar(1024) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT NULL,
-  [type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
+  [ext_name] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
+  [mime_type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
   [size] int  NOT NULL,
   [creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
   [create_time] datetime2(7)  NOT NULL,
   [updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
   [update_time] datetime2(7)  NOT NULL,
   [deleted] bit DEFAULT 0 NOT NULL,
-  [name] nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL
+  [name] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL
 )
 GO
 
@@ -2677,10 +2678,17 @@ EXEC sp_addextendedproperty
 GO
 
 EXEC sp_addextendedproperty
-'MS_Description', N'文件类型',
+'MS_Description', N'文件扩展名',
 'SCHEMA', N'dbo',
 'TABLE', N'infra_file',
-'COLUMN', N'type'
+'COLUMN', N'ext_name'
+GO
+
+EXEC sp_addextendedproperty
+'MS_Description', N'文件MIME类型',
+'SCHEMA', N'dbo',
+'TABLE', N'infra_file',
+'COLUMN', N'mime_type'
 GO
 
 EXEC sp_addextendedproperty

+ 7 - 6
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 {
      * @return 文件路径
      */
     default String createFile(byte[] content) {
-        return createFile(null, null, content);
+        return createFile(null, null, "application/octet-stream", content);
     }
 
     /**
@@ -25,17 +25,18 @@ public interface FileApi {
      * @return 文件路径
      */
     default String createFile(String path, byte[] content) {
-        return createFile(null, path, content);
+        return createFile(null, path, "application/octet-stream", content);
     }
 
     /**
      * 保存文件,并返回文件的访问路径
      *
-     * @param name 文件名称
-     * @param path 文件路径
-     * @param content 文件内容
+     * @param name     文件名称
+     * @param path     文件路径
+     * @param mimeType 文件类型
+     * @param content  文件内容
      * @return 文件路径
      */
-    String createFile(String name, String path, byte[] content);
+    String createFile(String name, String path, String mimeType, byte[] content);
 
 }

+ 2 - 2
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 {
     private FileService fileService;
 
     @Override
-    public String createFile(String name, String path, byte[] content) {
-        return fileService.createFile(name, path, content);
+    public String createFile(String name, String path, String mimeType, byte[] content) {
+        return fileService.createFile(name, path, mimeType, content);
     }
 
 }

+ 1 - 1
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 {
     @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
     public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
                                            @RequestParam(value = "path", required = false) String path) throws Exception {
-        return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
+        return success(fileService.createFile(file.getOriginalFilename(), path, file.getContentType(), IoUtil.readBytes(file.getInputStream())));
     }
 
     @DeleteMapping("/delete")

+ 8 - 4
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 {
      */
     private String name;
     /**
-     * 路径,即文件名
+     * 路径,即文件名,唯一不可重复
      */
     private String path;
     /**
@@ -46,11 +46,15 @@ public class FileDO extends BaseDO {
      */
     private String url;
     /**
-     * 文件类型
-     *
+     * 文件扩展名
+     * <p>
      * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
      */
-    private String type;
+    private String extName;
+    /**
+     * 文件的MIME类型,默认为"application/octet-stream"
+     */
+    private String mimeType;
     /**
      * 文件大小
      */

+ 1 - 1
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<FileDO> {
     default PageResult<FileDO> selectPage(FilePageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<FileDO>()
                 .likeIfPresent(FileDO::getPath, reqVO.getPath())
-                .likeIfPresent(FileDO::getType, reqVO.getType())
+                .likeIfPresent(FileDO::getExtName, reqVO.getType())
                 .betweenIfPresent(FileDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
                 .orderByDesc(FileDO::getId));
     }

+ 2 - 1
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 {
      *
      * @param name 文件名称
      * @param path 文件路径
+     * @param mimeType 文件MIME类型
      * @param content 文件内容
      * @return 文件路径
      */
-    String createFile(String name, String path, byte[] content);
+    String createFile(String name, String path, String mimeType,byte[] content);
 
     /**
      * 删除文件

+ 9 - 5
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.infra.service.file;
 
 import cn.hutool.core.io.FileTypeUtil;
+import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.digest.DigestUtil;
@@ -39,11 +40,13 @@ public class FileServiceImpl implements FileService {
 
     @Override
     @SneakyThrows
-    public String createFile(String name, String path, byte[] content) {
-        // 计算默认的 path 名
-        String type = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
+    public String createFile(String name, String path, String mimeType, byte[] content) {
+        //获取文件的真实扩展名
+        String extName = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
+        FileNameUtil.extName(name);
         if (StrUtil.isEmpty(path)) {
-            path = DigestUtil.md5Hex(content) + '.' + type;
+            //使用sha256计算文件都唯一路径,降低碰撞概率
+            path = DigestUtil.sha256Hex(content) + '.' + extName;
         }
         // 如果 name 为空,则使用 path 填充
         if (StrUtil.isEmpty(name)) {
@@ -61,7 +64,8 @@ public class FileServiceImpl implements FileService {
         file.setName(name);
         file.setPath(path);
         file.setUrl(url);
-        file.setType(type);
+        file.setExtName(extName);
+        file.setMimeType(mimeType);
         file.setSize(content.length);
         fileMapper.insert(file);
         return url;

+ 4 - 4
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 {
         // mock 数据
         FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
             o.setPath("yunai");
-            o.setType("jpg");
+            o.setExtName("jpg");
             o.setCreateTime(buildTime(2021, 1, 15));
         });
         fileMapper.insert(dbFile);
@@ -48,7 +48,7 @@ public class FileServiceTest extends BaseDbUnitTest {
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
         // 测试 type 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
-            o.setType("png");
+            o.setExtName("png");
         }));
         // 测试 createTime 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
@@ -82,7 +82,7 @@ public class FileServiceTest extends BaseDbUnitTest {
         when(client.getId()).thenReturn(10L);
         String name = "单测文件名";
         // 调用
-        String result = fileService.createFile(name, path, content);
+        String result = fileService.createFile(name, path, "application/octet-stream", content);
         // 断言
         assertEquals(result, url);
         // 校验数据
@@ -90,7 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest {
         assertEquals(10L, file.getConfigId());
         assertEquals(path, file.getPath());
         assertEquals(url, file.getUrl());
-        assertEquals("jpg", file.getType());
+        assertEquals("jpg", file.getExtName());
         assertEquals(content.length, file.getSize());
     }