From a68a97914910ca500c9fbd2d92a225fa82a1fe09 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Thu, 7 Jul 2022 09:40:23 +0800
Subject: [PATCH 01/13] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E5=90=8D=E5=92=8C=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E5=AD=97?=
 =?UTF-8?q?=E6=AE=B5=E9=95=BF=E5=BA=A6=E4=B8=80=E8=87=B4=EF=BC=8C=E5=9B=A0?=
 =?UTF-8?q?=E4=B8=BA=E5=A6=82=E6=9E=9C=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=96=87?=
 =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B=EF=BC=8C?=
 =?UTF-8?q?=E4=BC=9A=E4=BD=BF=E7=94=A8=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84?=
 =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=AD=97=E6=AE=B5=E5=90=8D=EF=BC=8C=E9=98=B2?=
 =?UTF-8?q?=E6=AD=A2=E6=95=B0=E6=8D=AE=E5=BA=93=E6=8A=A5=E9=94=99=E5=AD=97?=
 =?UTF-8?q?=E6=AE=B5=E5=86=85=E5=AE=B9=E5=A4=AA=E9=95=BF=E3=80=82=202.=20?=
 =?UTF-8?q?=E4=BF=AE=E6=94=B9type=E5=AD=97=E6=AE=B5=E4=B8=BAext=5Fname?=
 =?UTF-8?q?=EF=BC=8C=E5=9B=A0=E4=B8=BA=E6=AD=A4=E5=AD=97=E6=AE=B5=E6=9C=AC?=
 =?UTF-8?q?=E6=9D=A5=E5=B0=B1=E5=AD=98=E7=9A=84=E6=96=87=E4=BB=B6=E6=89=A9?=
 =?UTF-8?q?=E5=B1=95=E5=90=8D=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=96=B0=E5=A2=9E?=
 =?UTF-8?q?mime=5Ftype=E5=AD=97=E6=AE=B5=EF=BC=8C=E7=94=A8=E6=9D=A5?=
 =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=96=87=E4=BB=B6=E7=9A=84=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E3=80=82=E6=96=B9=E4=BE=BF=E5=90=8E=E6=9C=9F=E6=8B=93=E5=B1=95?=
 =?UTF-8?q?=E7=BD=91=E7=9B=98=E9=A1=B9=E7=9B=AE=E3=80=82=203.=20=E4=BF=AE?=
 =?UTF-8?q?=E6=94=B9=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E7=94=9F=E6=88=90?=
 =?UTF-8?q?=E6=96=B9=E5=BC=8F=EF=BC=9A=E4=B9=8B=E5=89=8D=E6=98=AFmd5?=
 =?UTF-8?q?=EF=BC=8C=E7=8E=B0=E5=9C=A8=E6=98=AFsha256=EF=BC=8C=E9=99=8D?=
 =?UTF-8?q?=E4=BD=8E=E6=96=87=E4=BB=B6=E7=A2=B0=E6=92=9E=E6=A6=82=E7=8E=87?=
 =?UTF-8?q?=E3=80=82=E6=96=B9=E4=BE=BF=E6=8B=93=E5=B1=95=E7=BD=91=E7=9B=98?=
 =?UTF-8?q?=E9=A1=B9=E7=9B=AE=EF=BC=8C=E5=AE=9E=E7=8E=B0=E7=A7=92=E4=BC=A0?=
 =?UTF-8?q?=E7=AD=89=E5=8A=9F=E8=83=BD=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 sql/mysql/ruoyi-vue-pro.sql                      |  5 +++--
 sql/oracle/ruoyi-vue-pro.sql                     |  6 ++++--
 sql/postgresql/ruoyi-vue-pro.sql                 |  8 +++++---
 sql/sqlserver/ruoyi-vue-pro.sql                  | 16 ++++++++++++----
 .../yudao/module/infra/api/file/FileApi.java     | 13 +++++++------
 .../yudao/module/infra/api/file/FileApiImpl.java |  4 ++--
 .../controller/admin/file/FileController.java    |  2 +-
 .../module/infra/dal/dataobject/file/FileDO.java | 12 ++++++++----
 .../module/infra/service/file/FileService.java   |  3 ++-
 .../infra/service/file/FileServiceImpl.java      | 14 +++++++++-----
 .../infra/service/file/FileServiceTest.java      |  8 ++++----
 11 files changed, 57 insertions(+), 34 deletions(-)

diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql
index a014a1b8c..e6baf5dc6 100644
--- a/sql/mysql/ruoyi-vue-pro.sql
+++ b/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 '创建时间',
diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql
index 1f4908645..614cac0f8 100644
--- a/sql/oracle/ruoyi-vue-pro.sql
+++ b/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 '创建时间';
diff --git a/sql/postgresql/ruoyi-vue-pro.sql b/sql/postgresql/ruoyi-vue-pro.sql
index 9e80ce70d..663a169f0 100644
--- a/sql/postgresql/ruoyi-vue-pro.sql
+++ b/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 '创建时间';
diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql
index d6bd1847c..40b01dac6 100644
--- a/sql/sqlserver/ruoyi-vue-pro.sql
+++ b/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
diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
index c41c6e039..85e629d25 100644
--- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
+++ b/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);
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
index 05fb946fe..851221374 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
+++ b/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);
     }
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
index fcdca025f..0ddd5dc43 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
+++ b/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")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
index 7e81280da..36ef56113 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
+++ b/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;
     /**
      * 文件大小
      */
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
index 24baf4218..07a7ebd59 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
+++ b/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);
 
     /**
      * 删除文件
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index b90e92752..cf6dc700b 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
index e61039385..21db8ac8a 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
+++ b/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());
     }
 

From 36d7775171d3fdc381414b84a450db93cafa92ef Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Thu, 7 Jul 2022 09:40:23 +0800
Subject: [PATCH 02/13] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E5=90=8D=E5=92=8C=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E5=AD=97?=
 =?UTF-8?q?=E6=AE=B5=E9=95=BF=E5=BA=A6=E4=B8=80=E8=87=B4=EF=BC=8C=E5=9B=A0?=
 =?UTF-8?q?=E4=B8=BA=E5=A6=82=E6=9E=9C=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=96=87?=
 =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B=EF=BC=8C?=
 =?UTF-8?q?=E4=BC=9A=E4=BD=BF=E7=94=A8=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84?=
 =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=AD=97=E6=AE=B5=E5=90=8D=EF=BC=8C=E9=98=B2?=
 =?UTF-8?q?=E6=AD=A2=E6=95=B0=E6=8D=AE=E5=BA=93=E6=8A=A5=E9=94=99=E5=AD=97?=
 =?UTF-8?q?=E6=AE=B5=E5=86=85=E5=AE=B9=E5=A4=AA=E9=95=BF=E3=80=82=202.=20?=
 =?UTF-8?q?=E4=BF=AE=E6=94=B9type=E5=AD=97=E6=AE=B5=E4=B8=BAext=5Fname?=
 =?UTF-8?q?=EF=BC=8C=E5=9B=A0=E4=B8=BA=E6=AD=A4=E5=AD=97=E6=AE=B5=E6=9C=AC?=
 =?UTF-8?q?=E6=9D=A5=E5=B0=B1=E5=AD=98=E7=9A=84=E6=96=87=E4=BB=B6=E6=89=A9?=
 =?UTF-8?q?=E5=B1=95=E5=90=8D=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=96=B0=E5=A2=9E?=
 =?UTF-8?q?mime=5Ftype=E5=AD=97=E6=AE=B5=EF=BC=8C=E7=94=A8=E6=9D=A5?=
 =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=96=87=E4=BB=B6=E7=9A=84=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E3=80=82=E6=96=B9=E4=BE=BF=E5=90=8E=E6=9C=9F=E6=8B=93=E5=B1=95?=
 =?UTF-8?q?=E7=BD=91=E7=9B=98=E9=A1=B9=E7=9B=AE=E3=80=82=203.=20=E4=BF=AE?=
 =?UTF-8?q?=E6=94=B9=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E7=94=9F=E6=88=90?=
 =?UTF-8?q?=E6=96=B9=E5=BC=8F=EF=BC=9A=E4=B9=8B=E5=89=8D=E6=98=AFmd5?=
 =?UTF-8?q?=EF=BC=8C=E7=8E=B0=E5=9C=A8=E6=98=AFsha256=EF=BC=8C=E9=99=8D?=
 =?UTF-8?q?=E4=BD=8E=E6=96=87=E4=BB=B6=E7=A2=B0=E6=92=9E=E6=A6=82=E7=8E=87?=
 =?UTF-8?q?=E3=80=82=E6=96=B9=E4=BE=BF=E6=8B=93=E5=B1=95=E7=BD=91=E7=9B=98?=
 =?UTF-8?q?=E9=A1=B9=E7=9B=AE=EF=BC=8C=E5=AE=9E=E7=8E=B0=E7=A7=92=E4=BC=A0?=
 =?UTF-8?q?=E7=AD=89=E5=8A=9F=E8=83=BD=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 sql/mysql/ruoyi-vue-pro.sql                      |  5 +++--
 sql/oracle/ruoyi-vue-pro.sql                     |  6 ++++--
 sql/postgresql/ruoyi-vue-pro.sql                 |  8 +++++---
 sql/sqlserver/ruoyi-vue-pro.sql                  | 16 ++++++++++++----
 .../yudao/module/infra/api/file/FileApi.java     | 13 +++++++------
 .../yudao/module/infra/api/file/FileApiImpl.java |  4 ++--
 .../controller/admin/file/FileController.java    |  2 +-
 .../module/infra/dal/dataobject/file/FileDO.java | 12 ++++++++----
 .../module/infra/dal/mysql/file/FileMapper.java  |  2 +-
 .../module/infra/service/file/FileService.java   |  3 ++-
 .../infra/service/file/FileServiceImpl.java      | 14 +++++++++-----
 .../infra/service/file/FileServiceTest.java      |  8 ++++----
 12 files changed, 58 insertions(+), 35 deletions(-)

diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql
index a014a1b8c..e6baf5dc6 100644
--- a/sql/mysql/ruoyi-vue-pro.sql
+++ b/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 '创建时间',
diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql
index 1f4908645..614cac0f8 100644
--- a/sql/oracle/ruoyi-vue-pro.sql
+++ b/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 '创建时间';
diff --git a/sql/postgresql/ruoyi-vue-pro.sql b/sql/postgresql/ruoyi-vue-pro.sql
index 9e80ce70d..663a169f0 100644
--- a/sql/postgresql/ruoyi-vue-pro.sql
+++ b/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 '创建时间';
diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql
index d6bd1847c..40b01dac6 100644
--- a/sql/sqlserver/ruoyi-vue-pro.sql
+++ b/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
diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
index c41c6e039..85e629d25 100644
--- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
+++ b/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);
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
index 05fb946fe..851221374 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
+++ b/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);
     }
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
index fcdca025f..0ddd5dc43 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
+++ b/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")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
index 7e81280da..36ef56113 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
+++ b/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;
     /**
      * 文件大小
      */
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
index 845addc14..8cf50cddc 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
+++ b/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));
     }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
index 24baf4218..07a7ebd59 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
+++ b/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);
 
     /**
      * 删除文件
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index b90e92752..cf6dc700b 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/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;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
index e61039385..21db8ac8a 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
+++ b/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());
     }
 

From b741ed480b0d0df9711d47c1bbe2dd692cfec126 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Thu, 7 Jul 2022 10:51:33 +0800
Subject: [PATCH 03/13] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=8A=E6=AC=A1?=
 =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=AF=BC=E8=87=B4=E7=9A=84=E5=89=8D=E7=AB=AF?=
 =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=8F=96=E5=80=BC=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../admin/file/vo/file/FilePageReqVO.java           |  4 ++--
 .../controller/admin/file/vo/file/FileRespVO.java   |  7 +++++--
 .../module/infra/dal/mysql/file/FileMapper.java     |  2 +-
 yudao-ui-admin/src/views/infra/file/index.vue       | 13 +++++++------
 4 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
index 346314e83..043cf11bb 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
@@ -21,8 +21,8 @@ public class FilePageReqVO extends PageParam {
     @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配")
     private String path;
 
-    @ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配")
-    private String type;
+    @ApiModelProperty(value = "文件扩展名", example = "jpg", notes = "模糊匹配")
+    private String extName;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @ApiModelProperty(value = "开始创建时间")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
index 10737693d..7a53bf2e1 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
@@ -22,8 +22,11 @@ public class FileRespVO {
     @ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg")
     private String url;
 
-    @ApiModelProperty(value = "文件类型", example = "jpg")
-    private String type;
+    @ApiModelProperty(value = "文件扩展名", example = "jpg")
+    private String extName;
+
+    @ApiModelProperty(value = "文件MIME类型", example = "application/octet-stream")
+    private String mimeType;
 
     @ApiModelProperty(value = "文件大小", example = "2048", required = true)
     private Integer size;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
index 8cf50cddc..28c37067c 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
+++ b/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::getExtName, reqVO.getType())
+                .likeIfPresent(FileDO::getExtName, reqVO.getExtName())
                 .betweenIfPresent(FileDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
                 .orderByDesc(FileDO::getId));
     }
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 462a879de..76e189c83 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -26,14 +26,15 @@
 
     <!-- 列表 -->
     <el-table v-loading="loading" :data="list">
-      <el-table-column label="文件名" align="center" prop="name" />
-      <el-table-column label="文件路径" align="center" prop="path" />
-      <el-table-column label="文件 URL" align="center" prop="url" />
+      <el-table-column  label="文件名" :show-overflow-tooltip="true" align="center" min-width="250" prop="name" />
+      <el-table-column :show-overflow-tooltip="true" label="文件路径" align="center" min-width="300" prop="path" />
+      <el-table-column :show-overflow-tooltip="true" label="文件 URL" align="center" min-width="400" prop="url" />
       <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" />
-      <el-table-column label="文件类型" align="center" prop="type" width="80" />
+      <el-table-column label="文件类型" align="center" prop="mimeType" width="210" />
+      <el-table-column label="文件扩展名" align="center" prop="extName" width="80" />
 <!--      <el-table-column label="文件内容" align="center" prop="content">-->
 <!--        <template slot-scope="scope">-->
-<!--          <img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'"-->
+<!--          <img v-if="scope.row.extName === 'jpg' || scope.row.extName === 'png' || scope.row.extName === 'gif'"-->
 <!--               width="200px" :src="getFileUrl + scope.row.id">-->
 <!--          <i v-else>非图片,无法预览</i>-->
 <!--        </template>-->
@@ -101,7 +102,7 @@ export default {
         pageNo: 1,
         pageSize: 10,
         path: null,
-        type: null,
+        extName: null,
       },
       // 用户导入参数
       upload: {

From 0ed332171989a4fc4a9744def85f58a6d0150f5e Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Fri, 8 Jul 2022 08:44:09 +0800
Subject: [PATCH 04/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E8=A1=A8=E8=A1=A8=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 sql/mysql/ruoyi-vue-pro.sql      |  3 +--
 sql/oracle/ruoyi-vue-pro.sql     |  6 ++----
 sql/postgresql/ruoyi-vue-pro.sql |  6 ++----
 sql/sqlserver/ruoyi-vue-pro.sql  | 12 ++----------
 4 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql
index e6baf5dc6..12e77d40f 100644
--- a/sql/mysql/ruoyi-vue-pro.sql
+++ b/sql/mysql/ruoyi-vue-pro.sql
@@ -692,8 +692,7 @@ CREATE TABLE `infra_file`  (
   `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',
-  `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类型',
+  `type` varchar(64) 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 '创建时间',
diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql
index 614cac0f8..07e0a85e3 100644
--- a/sql/oracle/ruoyi-vue-pro.sql
+++ b/sql/oracle/ruoyi-vue-pro.sql
@@ -878,8 +878,7 @@ CREATE TABLE "INFRA_FILE" (
   "CONFIG_ID" NUMBER(20,0),
   "PATH" NVARCHAR2(512),
   "URL" NCLOB,
-  "EXT_NAME" NVARCHAR2(63),
-  "MIME_TYPE" NVARCHAR2(63),
+  "TYPE" NVARCHAR2(64),
   "SIZE" NUMBER(11,0) NOT NULL,
   "CREATOR" NVARCHAR2(64),
   "CREATE_TIME" DATE NOT NULL,
@@ -909,8 +908,7 @@ 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"."EXT_NAME" IS '文件扩展名';
-COMMENT ON COLUMN "INFRA_FILE"."MIME_TYPE" IS '文件MIME类型';
+COMMENT ON COLUMN "INFRA_FILE"."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 '创建时间';
diff --git a/sql/postgresql/ruoyi-vue-pro.sql b/sql/postgresql/ruoyi-vue-pro.sql
index 663a169f0..a6575bccb 100644
--- a/sql/postgresql/ruoyi-vue-pro.sql
+++ b/sql/postgresql/ruoyi-vue-pro.sql
@@ -1717,8 +1717,7 @@ 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,
-  "ext_name" varchar(63) COLLATE "pg_catalog"."default",
-  "mime_type" varchar(63) COLLATE "pg_catalog"."default",
+  "type" varchar(64) COLLATE "pg_catalog"."default",
   "size" int4 NOT NULL,
   "creator" varchar(64) COLLATE "pg_catalog"."default",
   "create_time" timestamp(6) NOT NULL,
@@ -1732,8 +1731,7 @@ 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"."ext_name" IS '文件扩展名';
-COMMENT ON COLUMN "infra_file"."mime_type" IS '文件MIME类型';
+COMMENT ON COLUMN "infra_file"."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 '创建时间';
diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql
index 40b01dac6..6e058e02e 100644
--- a/sql/sqlserver/ruoyi-vue-pro.sql
+++ b/sql/sqlserver/ruoyi-vue-pro.sql
@@ -2634,8 +2634,7 @@ 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,
-  [ext_name] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
-  [mime_type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL,
+  [type] nvarchar(64) 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,
@@ -2677,18 +2676,11 @@ EXEC sp_addextendedproperty
 'COLUMN', N'url'
 GO
 
-EXEC sp_addextendedproperty
-'MS_Description', N'文件扩展名',
-'SCHEMA', N'dbo',
-'TABLE', N'infra_file',
-'COLUMN', N'ext_name'
-GO
-
 EXEC sp_addextendedproperty
 'MS_Description', N'文件MIME类型',
 'SCHEMA', N'dbo',
 'TABLE', N'infra_file',
-'COLUMN', N'mime_type'
+'COLUMN', N'type'
 GO
 
 EXEC sp_addextendedproperty

From da0ba105033c3d51865793274f7c06644dde32a8 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Fri, 8 Jul 2022 09:14:39 +0800
Subject: [PATCH 05/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9mimetype=E5=AD=97?=
 =?UTF-8?q?=E6=AE=B5=E4=B8=BAtype=EF=BC=8C=E4=BF=AE=E6=94=B9=E8=8E=B7?=
 =?UTF-8?q?=E5=8F=96=E6=96=87=E4=BB=B6=E5=90=8E=E7=BC=80=E5=90=8D=E6=96=B9?=
 =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E7=9B=AE=E5=89=8D=E5=9B=BE=E7=89=87=E6=96=87?=
 =?UTF-8?q?=E4=BB=B6=E9=A2=84=E8=A7=88=E8=BF=98=E6=9C=89=E4=BA=9B=E9=97=AE?=
 =?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../controller/admin/file/vo/file/FilePageReqVO.java  |  4 ++--
 .../controller/admin/file/vo/file/FileRespVO.java     |  5 +----
 .../module/infra/dal/dataobject/file/FileDO.java      |  9 ++-------
 .../yudao/module/infra/dal/mysql/file/FileMapper.java |  2 +-
 .../module/infra/service/file/FileServiceImpl.java    | 11 +++++------
 .../module/infra/service/file/FileServiceTest.java    |  6 ------
 yudao-ui-admin/src/views/infra/file/index.vue         |  8 +++-----
 7 files changed, 14 insertions(+), 31 deletions(-)

diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
index 043cf11bb..e803fcf25 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
@@ -21,8 +21,8 @@ public class FilePageReqVO extends PageParam {
     @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配")
     private String path;
 
-    @ApiModelProperty(value = "文件扩展名", example = "jpg", notes = "模糊匹配")
-    private String extName;
+    @ApiModelProperty(value = "文件类型", example = "application/octet-stream", notes = "模糊匹配")
+    private String type;
 
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @ApiModelProperty(value = "开始创建时间")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
index 7a53bf2e1..fa6ec8444 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
@@ -22,11 +22,8 @@ public class FileRespVO {
     @ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg")
     private String url;
 
-    @ApiModelProperty(value = "文件扩展名", example = "jpg")
-    private String extName;
-
     @ApiModelProperty(value = "文件MIME类型", example = "application/octet-stream")
-    private String mimeType;
+    private String type;
 
     @ApiModelProperty(value = "文件大小", example = "2048", required = true)
     private Integer size;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
index 36ef56113..ae898c8cd 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
@@ -45,16 +45,11 @@ public class FileDO extends BaseDO {
      * 访问地址
      */
     private String url;
-    /**
-     * 文件扩展名
-     * <p>
-     * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
-     */
-    private String extName;
+
     /**
      * 文件的MIME类型,默认为"application/octet-stream"
      */
-    private String mimeType;
+    private String type;
     /**
      * 文件大小
      */
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
index 28c37067c..845addc14 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java
+++ b/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::getExtName, reqVO.getExtName())
+                .likeIfPresent(FileDO::getType, reqVO.getType())
                 .betweenIfPresent(FileDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
                 .orderByDesc(FileDO::getId));
     }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index cf6dc700b..0df38d22c 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
@@ -41,12 +41,12 @@ public class FileServiceImpl implements FileService {
     @Override
     @SneakyThrows
     public String createFile(String name, String path, String mimeType, byte[] content) {
-        //获取文件的真实扩展名
-        String extName = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
-        FileNameUtil.extName(name);
+        //获取文件的扩展名
+        String extName = FileNameUtil.extName(name);
         if (StrUtil.isEmpty(path)) {
             //使用sha256计算文件都唯一路径,降低碰撞概率
-            path = DigestUtil.sha256Hex(content) + '.' + extName;
+            String sha256Hex = DigestUtil.sha256Hex(content);
+            path = StrUtil.isBlank(extName) ? sha256Hex : (sha256Hex + '.' + extName);
         }
         // 如果 name 为空,则使用 path 填充
         if (StrUtil.isEmpty(name)) {
@@ -64,8 +64,7 @@ public class FileServiceImpl implements FileService {
         file.setName(name);
         file.setPath(path);
         file.setUrl(url);
-        file.setExtName(extName);
-        file.setMimeType(mimeType);
+        file.setType(mimeType);
         file.setSize(content.length);
         fileMapper.insert(file);
         return url;
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
index 21db8ac8a..a4e9966a5 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
@@ -40,16 +40,11 @@ public class FileServiceTest extends BaseDbUnitTest {
         // mock 数据
         FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
             o.setPath("yunai");
-            o.setExtName("jpg");
             o.setCreateTime(buildTime(2021, 1, 15));
         });
         fileMapper.insert(dbFile);
         // 测试 path 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
-        // 测试 type 不匹配
-        fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
-            o.setExtName("png");
-        }));
         // 测试 createTime 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
             o.setCreateTime(buildTime(2020, 1, 15));
@@ -90,7 +85,6 @@ public class FileServiceTest extends BaseDbUnitTest {
         assertEquals(10L, file.getConfigId());
         assertEquals(path, file.getPath());
         assertEquals(url, file.getUrl());
-        assertEquals("jpg", file.getExtName());
         assertEquals(content.length, file.getSize());
     }
 
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 76e189c83..5bcf721a3 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -30,11 +30,10 @@
       <el-table-column :show-overflow-tooltip="true" label="文件路径" align="center" min-width="300" prop="path" />
       <el-table-column :show-overflow-tooltip="true" label="文件 URL" align="center" min-width="400" prop="url" />
       <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" />
-      <el-table-column label="文件类型" align="center" prop="mimeType" width="210" />
-      <el-table-column label="文件扩展名" align="center" prop="extName" width="80" />
+      <el-table-column label="文件类型" align="center" prop="type" width="210" />
 <!--      <el-table-column label="文件内容" align="center" prop="content">-->
 <!--        <template slot-scope="scope">-->
-<!--          <img v-if="scope.row.extName === 'jpg' || scope.row.extName === 'png' || scope.row.extName === 'gif'"-->
+<!--          <img v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0"-->
 <!--               width="200px" :src="getFileUrl + scope.row.id">-->
 <!--          <i v-else>非图片,无法预览</i>-->
 <!--        </template>-->
@@ -101,8 +100,7 @@ export default {
       queryParams: {
         pageNo: 1,
         pageSize: 10,
-        path: null,
-        extName: null,
+        path: null
       },
       // 用户导入参数
       upload: {

From eb3228d4c781ff21418acf93e8ed4036a72520db Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Fri, 8 Jul 2022 11:02:21 +0800
Subject: [PATCH 06/13] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=88=97=E8=A1=A8?=
 =?UTF-8?q?=E4=BC=9A=E6=98=BE=E7=A4=BA=E5=9B=BE=E7=89=87=E7=BC=A9=E7=95=A5?=
 =?UTF-8?q?=E5=9B=BE=EF=BC=8C=E7=82=B9=E5=87=BB=E7=BC=A9=E7=95=A5=E5=9B=BE?=
 =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E9=A2=84=E8=A7=88=E5=A4=A7=E5=9B=BE=E3=80=82?=
 =?UTF-8?q?=E9=9D=9E=E5=9B=BE=E7=89=87=E6=96=87=E4=BB=B6=E5=9C=A8=E5=88=97?=
 =?UTF-8?q?=E8=A1=A8=E9=A1=B5=E9=9D=A2=E4=BC=9A=E6=98=BE=E7=A4=BA=E4=B8=8B?=
 =?UTF-8?q?=E8=BD=BD=E6=8C=89=E9=92=AE=E3=80=82=E7=82=B9=E5=87=BB=E5=8D=B3?=
 =?UTF-8?q?=E5=8F=AF=E4=B8=8B=E8=BD=BD=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../admin/file/vo/file/FileRespVO.java        |  3 +++
 yudao-ui-admin/src/views/infra/file/index.vue | 24 ++++++++++++-------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
index fa6ec8444..31b790a21 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java
@@ -13,6 +13,9 @@ public class FileRespVO {
     @ApiModelProperty(value = "文件编号", required = true, example = "1024")
     private Long id;
 
+    @ApiModelProperty(value = "配置编号", required = true, example = "11")
+    private Long configId;
+
     @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg")
     private String path;
 
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 5bcf721a3..6f368d5c0 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -31,13 +31,17 @@
       <el-table-column :show-overflow-tooltip="true" label="文件 URL" align="center" min-width="400" prop="url" />
       <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" />
       <el-table-column label="文件类型" align="center" prop="type" width="210" />
-<!--      <el-table-column label="文件内容" align="center" prop="content">-->
-<!--        <template slot-scope="scope">-->
-<!--          <img v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0"-->
-<!--               width="200px" :src="getFileUrl + scope.row.id">-->
-<!--          <i v-else>非图片,无法预览</i>-->
-<!--        </template>-->
-<!--      </el-table-column>-->
+      <el-table-column label="文件内容" align="center" prop="content" min-width="150px">
+        <template slot-scope="scope">
+          <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url"
+                         :width="'100px'"></image-preview>
+          <i v-else>无法预览,点击
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
+                     :href="getFileUrl+scope.row.configId+'/get/' + scope.row.path">下载
+            </el-link>
+          </i>
+        </template>
+      </el-table-column>
       <el-table-column label="上传时间" align="center" prop="createTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.createTime) }}</span>
@@ -79,12 +83,16 @@
 <script>
 import { deleteFile, getFilePage } from "@/api/infra/file";
 import {getAccessToken} from "@/utils/auth";
+import ImagePreview from "@/components/ImagePreview";
 
 export default {
   name: "File",
+  components: {
+    ImagePreview
+  },
   data() {
     return {
-      getFileUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/get/',
+      getFileUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/',
       // 遮罩层
       loading: true,
       // 显示搜索条件

From 84ef0b449a418ce51472f84f8b04f393fec10bd3 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Fri, 8 Jul 2022 11:59:21 +0800
Subject: [PATCH 07/13] =?UTF-8?q?SocialUserBindDO=E7=B1=BB=E6=96=B0?=
 =?UTF-8?q?=E5=A2=9E=E4=B8=BB=E9=94=AE=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=90=A6?=
 =?UTF-8?q?=E5=88=99=E6=8E=A7=E5=88=B6=E5=8F=B0=E4=BC=9A=E6=9C=89mybatis?=
 =?UTF-8?q?=20plus=E7=9A=84=E6=97=A5=E5=BF=97=E8=AD=A6=E5=91=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../system/dal/dataobject/social/SocialUserBindDO.java      | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserBindDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserBindDO.java
index c5dd5f4ac..0f4e41f96 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserBindDO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserBindDO.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
@@ -21,6 +22,11 @@ import lombok.*;
 @AllArgsConstructor
 public class SocialUserBindDO extends BaseDO {
 
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
     /**
      * 关联的用户编号
      *

From c64295f432999bc3cb76f06931fc50ef7ccc0dfc Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 10:41:06 +0800
Subject: [PATCH 08/13] =?UTF-8?q?=E5=90=88=E5=B9=B6fetch=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../yudao/module/infra/api/file/FileApi.java        | 13 ++++++-------
 .../yudao/module/infra/api/file/FileApiImpl.java    |  4 ++--
 .../infra/controller/admin/file/FileController.java |  2 +-
 .../module/infra/dal/dataobject/file/FileDO.java    |  5 ++---
 .../module/infra/service/file/FileService.java      |  3 +--
 .../module/infra/service/file/FileServiceTest.java  |  8 +++++++-
 yudao-ui-admin/src/views/infra/file/index.vue       |  3 ++-
 7 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
index 85e629d25..c41c6e039 100644
--- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java
+++ b/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, "application/octet-stream", content);
+        return createFile(null, null, content);
     }
 
     /**
@@ -25,18 +25,17 @@ public interface FileApi {
      * @return 文件路径
      */
     default String createFile(String path, byte[] content) {
-        return createFile(null, path, "application/octet-stream", content);
+        return createFile(null, path, content);
     }
 
     /**
      * 保存文件,并返回文件的访问路径
      *
-     * @param name     文件名称
-     * @param path     文件路径
-     * @param mimeType 文件类型
-     * @param content  文件内容
+     * @param name 文件名称
+     * @param path 文件路径
+     * @param content 文件内容
      * @return 文件路径
      */
-    String createFile(String name, String path, String mimeType, byte[] content);
+    String createFile(String name, String path, byte[] content);
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
index 851221374..05fb946fe 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
+++ b/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, String mimeType, byte[] content) {
-        return fileService.createFile(name, path, mimeType, content);
+    public String createFile(String name, String path, byte[] content) {
+        return fileService.createFile(name, path, content);
     }
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
index 7c3b7d574..5ea52b7e5 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
@@ -47,7 +47,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, file.getContentType(), IoUtil.readBytes(file.getInputStream())));
+        return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
     }
 
     @DeleteMapping("/delete")
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
index ae898c8cd..7c242d4eb 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
@@ -38,16 +38,15 @@ public class FileDO extends BaseDO {
      */
     private String name;
     /**
-     * 路径,即文件名,唯一不可重复
+     * 路径,即文件名
      */
     private String path;
     /**
      * 访问地址
      */
     private String url;
-
     /**
-     * 文件的MIME类型,默认为"application/octet-stream"
+     * 文件的MIME类型,例如"application/octet-stream"
      */
     private String type;
     /**
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
index 07a7ebd59..24baf4218 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java
@@ -24,11 +24,10 @@ public interface FileService {
      *
      * @param name 文件名称
      * @param path 文件路径
-     * @param mimeType 文件MIME类型
      * @param content 文件内容
      * @return 文件路径
      */
-    String createFile(String name, String path, String mimeType,byte[] content);
+    String createFile(String name, String path, byte[] content);
 
     /**
      * 删除文件
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
index a4e9966a5..b5acbb8a4 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
@@ -40,11 +40,16 @@ public class FileServiceTest extends BaseDbUnitTest {
         // mock 数据
         FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
             o.setPath("yunai");
+            o.setType("image/jpg");
             o.setCreateTime(buildTime(2021, 1, 15));
         });
         fileMapper.insert(dbFile);
         // 测试 path 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
+        // 测试 type 不匹配
+        fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
+            o.setType("image/png");
+        }));
         // 测试 createTime 不匹配
         fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
             o.setCreateTime(buildTime(2020, 1, 15));
@@ -77,7 +82,7 @@ public class FileServiceTest extends BaseDbUnitTest {
         when(client.getId()).thenReturn(10L);
         String name = "单测文件名";
         // 调用
-        String result = fileService.createFile(name, path, "application/octet-stream", content);
+        String result = fileService.createFile(name, path, content);
         // 断言
         assertEquals(result, url);
         // 校验数据
@@ -85,6 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest {
         assertEquals(10L, file.getConfigId());
         assertEquals(path, file.getPath());
         assertEquals(url, file.getUrl());
+        assertEquals("image/jpg", file.getType());
         assertEquals(content.length, file.getSize());
     }
 
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 6f368d5c0..838fe492a 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -108,7 +108,8 @@ export default {
       queryParams: {
         pageNo: 1,
         pageSize: 10,
-        path: null
+        path: null,
+        type: null,
       },
       // 用户导入参数
       upload: {

From a5d16c11e8a63db84ff9597f9807e9c3d914ccf8 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 11:27:45 +0800
Subject: [PATCH 09/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8E=B7=E5=8F=96mimet?=
 =?UTF-8?q?ype=E6=96=B9=E5=BC=8F=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=9F?=
 =?UTF-8?q?=E6=88=90path=E6=96=B9=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../file/core/utils/FileTypeUtils.java        | 31 +++++++++++++++----
 .../infra/service/file/FileServiceImpl.java   | 15 +++++++--
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
index d21b4879a..b623d364a 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
@@ -4,8 +4,6 @@ import com.alibaba.ttl.TransmittableThreadLocal;
 import lombok.SneakyThrows;
 import org.apache.tika.Tika;
 
-import java.io.ByteArrayInputStream;
-
 /**
  * 文件类型 Utils
  *
@@ -16,14 +14,35 @@ public class FileTypeUtils {
     private static final ThreadLocal<Tika> TIKA = TransmittableThreadLocal.withInitial(Tika::new);
 
     /**
-     * 获得文件的 mineType
+     * 获得文件的 mineType,对于doc,jar等文件会有误差
      *
-     * @param data 文件内容
-     * @return mineType
+     * @param data 包含文件开头几千个字节的字节数组
+     * @return mineType 无法识别时会返回“application/octet-stream”
      */
     @SneakyThrows
     public static String getMineType(byte[] data) {
-        return TIKA.get().detect(new ByteArrayInputStream(data));
+        return TIKA.get().detect(data);
+    }
+
+    /**
+     * 已知文件名,获取文件类型,在某些情况下比通过字节数组准确,例如使用jar文件时,通过名字更为准确
+     *
+     * @param name 文件名
+     * @return mineType 无法识别时会返回“application/octet-stream”
+     */
+    public static String getMineType(String name) {
+        return TIKA.get().detect(name);
+    }
+
+    /**
+     * 在拥有文件和数据的情况下,最好使用此方法,最为准确
+     *
+     * @param data 包含文件开头几千个字节的字节数组
+     * @param name 文件名
+     * @return mineType 无法识别时会返回“application/octet-stream”
+     */
+    public static String getMineType(byte[] data, String name) {
+        return TIKA.get().detect(data, name);
     }
 
 }
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index 98af005f7..f4aac3014 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
@@ -1,5 +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;
@@ -13,6 +15,7 @@ import lombok.SneakyThrows;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.io.ByteArrayInputStream;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;
@@ -40,10 +43,16 @@ public class FileServiceImpl implements FileService {
     @SneakyThrows
     public String createFile(String name, String path, byte[] content) {
         // 计算默认的 path 名
-        String type = FileTypeUtils.getMineType(content);
+        String type = FileTypeUtils.getMineType(content, name);
         if (StrUtil.isEmpty(path)) {
-            path = DigestUtil.md5Hex(content)
-                    + '.' + StrUtil.subAfter(type, '/', true); // 文件的后缀
+            String sha256Hex = DigestUtil.sha256Hex(content);
+            /*  如果存在name,则优先使用name的后缀 */
+            if (StrUtil.isNotBlank(name)) {
+                String extName = FileNameUtil.extName(name);
+                path = StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName;
+            } else {
+                path = sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content), name);
+            }
         }
         // 如果 name 为空,则使用 path 填充
         if (StrUtil.isEmpty(name)) {

From 30f2c1a496461f6c2ac9e1d1ec6b2fde305e798d Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 14:25:45 +0800
Subject: [PATCH 10/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=A1=B5=E9=9D=A2=E5=9C=A8=E5=B0=8F=E5=B1=8F?=
 =?UTF-8?q?=E5=B9=95=E4=B8=8A=E7=9A=84=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 yudao-ui-admin/src/views/infra/file/index.vue | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 838fe492a..5f5c53b46 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -26,11 +26,11 @@
 
     <!-- 列表 -->
     <el-table v-loading="loading" :data="list">
-      <el-table-column  label="文件名" :show-overflow-tooltip="true" align="center" min-width="250" prop="name" />
-      <el-table-column :show-overflow-tooltip="true" label="文件路径" align="center" min-width="300" prop="path" />
-      <el-table-column :show-overflow-tooltip="true" label="文件 URL" align="center" min-width="400" prop="url" />
-      <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" />
-      <el-table-column label="文件类型" align="center" prop="type" width="210" />
+      <el-table-column label="文件名" :show-overflow-tooltip="true" align="center" min-width="200px" prop="name"/>
+      <el-table-column label="文件路径" :show-overflow-tooltip="true" align="center" min-width="250px" prop="path"/>
+      <el-table-column label="文件 URL" :show-overflow-tooltip="true" align="center" min-width="300px" prop="url"/>
+      <el-table-column label="文件大小" align="center" prop="size" min-width="120px" :formatter="sizeFormat"/>
+      <el-table-column label="文件类型" :show-overflow-tooltip="true" align="center" prop="type" width="180px"/>
       <el-table-column label="文件内容" align="center" prop="content" min-width="150px">
         <template slot-scope="scope">
           <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url"
@@ -42,15 +42,16 @@
           </i>
         </template>
       </el-table-column>
-      <el-table-column label="上传时间" align="center" prop="createTime" width="180">
+      <el-table-column label="上传时间" align="center" prop="createTime" min-width="170px">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.createTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100">
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="100px">
         <template slot-scope="scope">
           <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
-                     v-hasPermi="['infra:file:delete']">删除</el-button>
+                     v-hasPermi="['infra:file:delete']">删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -81,7 +82,7 @@
 </template>
 
 <script>
-import { deleteFile, getFilePage } from "@/api/infra/file";
+import {deleteFile, getFilePage} from "@/api/infra/file";
 import {getAccessToken} from "@/utils/auth";
 import ImagePreview from "@/components/ImagePreview";
 

From dd726f79852de6b01e7cd5120594b3f58b984687 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 17:11:39 +0800
Subject: [PATCH 11/13] =?UTF-8?q?=E4=B8=AD=E8=8B=B1=E6=96=87=E4=B9=8B?=
 =?UTF-8?q?=E9=97=B4=E5=8A=A0=E7=A9=BA=E6=A0=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 sql/sqlserver/ruoyi-vue-pro.sql | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql
index 6e058e02e..1c0d93776 100644
--- a/sql/sqlserver/ruoyi-vue-pro.sql
+++ b/sql/sqlserver/ruoyi-vue-pro.sql
@@ -2677,7 +2677,7 @@ EXEC sp_addextendedproperty
 GO
 
 EXEC sp_addextendedproperty
-'MS_Description', N'文件MIME类型',
+'MS_Description', N'文件 MIME 类型',
 'SCHEMA', N'dbo',
 'TABLE', N'infra_file',
 'COLUMN', N'type'

From 2621f2195d1bacfbc56d143ff827bd1d717e6a8d Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 17:46:29 +0800
Subject: [PATCH 12/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../framework/common/util/io/FileUtils.java   | 21 +++++++++++++++++--
 .../file/core/utils/FileTypeUtils.java        |  4 ++--
 .../infra/service/file/FileServiceImpl.java   | 15 +++----------
 yudao-ui-admin/src/views/infra/file/index.vue |  2 +-
 4 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/FileUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/FileUtils.java
index 89fab2da2..f6cb2c82d 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/FileUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/FileUtils.java
@@ -1,9 +1,14 @@
 package cn.iocoder.yudao.framework.common.util.io;
 
+import cn.hutool.core.io.FileTypeUtil;
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.digest.DigestUtil;
 import lombok.SneakyThrows;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 
 /**
@@ -58,8 +63,20 @@ public class FileUtils {
         return file;
     }
 
-
-    public static void main(String[] args) {
+    /**
+     * @param content      文件内容
+     * @param originalName 原始文件名
+     * @return path,唯一不可重复
+     */
+    public static String generatePath(byte[] content, String originalName) {
+        String sha256Hex = DigestUtil.sha256Hex(content);
+        // 如果存在name,则优先使用name的后缀
+        if (StrUtil.isNotBlank(originalName)) {
+            String extName = FileNameUtil.extName(originalName);
+            return StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName;
+        } else {
+            return sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content));
+        }
     }
 
 }
diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
index b623d364a..8b99227b1 100644
--- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/utils/FileTypeUtils.java
@@ -16,7 +16,7 @@ public class FileTypeUtils {
     /**
      * 获得文件的 mineType,对于doc,jar等文件会有误差
      *
-     * @param data 包含文件开头几千个字节的字节数组
+     * @param data 文件内容
      * @return mineType 无法识别时会返回“application/octet-stream”
      */
     @SneakyThrows
@@ -37,7 +37,7 @@ public class FileTypeUtils {
     /**
      * 在拥有文件和数据的情况下,最好使用此方法,最为准确
      *
-     * @param data 包含文件开头几千个字节的字节数组
+     * @param data 文件内容
      * @param name 文件名
      * @return mineType 无法识别时会返回“application/octet-stream”
      */
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
index f4aac3014..c69eddfa4 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
@@ -1,11 +1,10 @@
 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.io.FileUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.digest.DigestUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.io.FileUtils;
 import cn.iocoder.yudao.framework.file.core.client.FileClient;
 import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils;
 import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
@@ -15,7 +14,6 @@ import lombok.SneakyThrows;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.io.ByteArrayInputStream;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;
@@ -45,14 +43,7 @@ public class FileServiceImpl implements FileService {
         // 计算默认的 path 名
         String type = FileTypeUtils.getMineType(content, name);
         if (StrUtil.isEmpty(path)) {
-            String sha256Hex = DigestUtil.sha256Hex(content);
-            /*  如果存在name,则优先使用name的后缀 */
-            if (StrUtil.isNotBlank(name)) {
-                String extName = FileNameUtil.extName(name);
-                path = StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName;
-            } else {
-                path = sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content), name);
-            }
+            path = FileUtils.generatePath(content, name);
         }
         // 如果 name 为空,则使用 path 填充
         if (StrUtil.isEmpty(name)) {
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 5f5c53b46..02de6410c 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -37,7 +37,7 @@
                          :width="'100px'"></image-preview>
           <i v-else>无法预览,点击
             <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
-                     :href="getFileUrl+scope.row.configId+'/get/' + scope.row.path">下载
+                     :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载
             </el-link>
           </i>
         </template>

From 1f5c3e7484f349ecbc0bdfa35a84cdb59c4a1dc5 Mon Sep 17 00:00:00 2001
From: jiangqiang <jq1257403419@vip.qq.com>
Date: Sat, 9 Jul 2022 17:55:22 +0800
Subject: [PATCH 13/13] =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E9=93=BE=E6=8E=A5?=
 =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9Etarget=3D"=5Fblank"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 yudao-ui-admin/src/views/infra/file/index.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 02de6410c..53716782e 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -36,7 +36,7 @@
           <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url"
                          :width="'100px'"></image-preview>
           <i v-else>无法预览,点击
-            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" target="_blank"
                      :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载
             </el-link>
           </i>