Commit b0d635e1f0058bb45094568c5d3cb835a9bf7cea
Committed by
Gitee
!210 文件表type字段修改
Merge pull request !210 from 随心/master
Showing
13 changed files
with
98 additions
and
46 deletions
sql/mysql/ruoyi-vue-pro.sql
| @@ -689,10 +689,10 @@ DROP TABLE IF EXISTS `infra_file`; | @@ -689,10 +689,10 @@ DROP TABLE IF EXISTS `infra_file`; | ||
| 689 | CREATE TABLE `infra_file` ( | 689 | CREATE TABLE `infra_file` ( |
| 690 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号', | 690 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号', |
| 691 | `config_id` bigint NULL DEFAULT NULL COMMENT '配置编号', | 691 | `config_id` bigint NULL DEFAULT NULL COMMENT '配置编号', |
| 692 | - `name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名', | 692 | + `name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件名', |
| 693 | `path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件路径', | 693 | `path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件路径', |
| 694 | `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件 URL', | 694 | `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件 URL', |
| 695 | - `type` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件类型', | 695 | + `type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '文件MIME类型', |
| 696 | `size` int NOT NULL COMMENT '文件大小', | 696 | `size` int NOT NULL COMMENT '文件大小', |
| 697 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | 697 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 698 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | 698 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
sql/oracle/ruoyi-vue-pro.sql
| @@ -878,7 +878,7 @@ CREATE TABLE "INFRA_FILE" ( | @@ -878,7 +878,7 @@ CREATE TABLE "INFRA_FILE" ( | ||
| 878 | "CONFIG_ID" NUMBER(20,0), | 878 | "CONFIG_ID" NUMBER(20,0), |
| 879 | "PATH" NVARCHAR2(512), | 879 | "PATH" NVARCHAR2(512), |
| 880 | "URL" NCLOB, | 880 | "URL" NCLOB, |
| 881 | - "TYPE" NVARCHAR2(63), | 881 | + "TYPE" NVARCHAR2(64), |
| 882 | "SIZE" NUMBER(11,0) NOT NULL, | 882 | "SIZE" NUMBER(11,0) NOT NULL, |
| 883 | "CREATOR" NVARCHAR2(64), | 883 | "CREATOR" NVARCHAR2(64), |
| 884 | "CREATE_TIME" DATE NOT NULL, | 884 | "CREATE_TIME" DATE NOT NULL, |
| @@ -908,7 +908,7 @@ COMMENT ON COLUMN "INFRA_FILE"."ID" IS '文件编号'; | @@ -908,7 +908,7 @@ COMMENT ON COLUMN "INFRA_FILE"."ID" IS '文件编号'; | ||
| 908 | COMMENT ON COLUMN "INFRA_FILE"."CONFIG_ID" IS '配置编号'; | 908 | COMMENT ON COLUMN "INFRA_FILE"."CONFIG_ID" IS '配置编号'; |
| 909 | COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径'; | 909 | COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径'; |
| 910 | COMMENT ON COLUMN "INFRA_FILE"."URL" IS '文件 URL'; | 910 | COMMENT ON COLUMN "INFRA_FILE"."URL" IS '文件 URL'; |
| 911 | -COMMENT ON COLUMN "INFRA_FILE"."TYPE" IS '文件类型'; | 911 | +COMMENT ON COLUMN "INFRA_FILE"."TYPE" IS '文件MIME类型'; |
| 912 | COMMENT ON COLUMN "INFRA_FILE"."SIZE" IS '文件大小'; | 912 | COMMENT ON COLUMN "INFRA_FILE"."SIZE" IS '文件大小'; |
| 913 | COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者'; | 913 | COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者'; |
| 914 | COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间'; | 914 | COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间'; |
sql/postgresql/ruoyi-vue-pro.sql
| @@ -1717,21 +1717,21 @@ CREATE TABLE "infra_file" ( | @@ -1717,21 +1717,21 @@ CREATE TABLE "infra_file" ( | ||
| 1717 | "config_id" int8, | 1717 | "config_id" int8, |
| 1718 | "path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL, | 1718 | "path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL, |
| 1719 | "url" varchar(1024) COLLATE "pg_catalog"."default" NOT NULL, | 1719 | "url" varchar(1024) COLLATE "pg_catalog"."default" NOT NULL, |
| 1720 | - "type" varchar(63) COLLATE "pg_catalog"."default", | 1720 | + "type" varchar(64) COLLATE "pg_catalog"."default", |
| 1721 | "size" int4 NOT NULL, | 1721 | "size" int4 NOT NULL, |
| 1722 | "creator" varchar(64) COLLATE "pg_catalog"."default", | 1722 | "creator" varchar(64) COLLATE "pg_catalog"."default", |
| 1723 | "create_time" timestamp(6) NOT NULL, | 1723 | "create_time" timestamp(6) NOT NULL, |
| 1724 | "updater" varchar(64) COLLATE "pg_catalog"."default", | 1724 | "updater" varchar(64) COLLATE "pg_catalog"."default", |
| 1725 | "update_time" timestamp(6) NOT NULL, | 1725 | "update_time" timestamp(6) NOT NULL, |
| 1726 | "deleted" int2 NOT NULL DEFAULT 0, | 1726 | "deleted" int2 NOT NULL DEFAULT 0, |
| 1727 | - "name" varchar(255) COLLATE "pg_catalog"."default" | 1727 | + "name" varchar(512) COLLATE "pg_catalog"."default" |
| 1728 | ) | 1728 | ) |
| 1729 | ; | 1729 | ; |
| 1730 | COMMENT ON COLUMN "infra_file"."id" IS '文件编号'; | 1730 | COMMENT ON COLUMN "infra_file"."id" IS '文件编号'; |
| 1731 | COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号'; | 1731 | COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号'; |
| 1732 | COMMENT ON COLUMN "infra_file"."path" IS '文件路径'; | 1732 | COMMENT ON COLUMN "infra_file"."path" IS '文件路径'; |
| 1733 | COMMENT ON COLUMN "infra_file"."url" IS '文件 URL'; | 1733 | COMMENT ON COLUMN "infra_file"."url" IS '文件 URL'; |
| 1734 | -COMMENT ON COLUMN "infra_file"."type" IS '文件类型'; | 1734 | +COMMENT ON COLUMN "infra_file"."type" IS '文件MIME类型'; |
| 1735 | COMMENT ON COLUMN "infra_file"."size" IS '文件大小'; | 1735 | COMMENT ON COLUMN "infra_file"."size" IS '文件大小'; |
| 1736 | COMMENT ON COLUMN "infra_file"."creator" IS '创建者'; | 1736 | COMMENT ON COLUMN "infra_file"."creator" IS '创建者'; |
| 1737 | COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间'; | 1737 | COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间'; |
sql/sqlserver/ruoyi-vue-pro.sql
| @@ -2634,14 +2634,14 @@ CREATE TABLE [dbo].[infra_file] ( | @@ -2634,14 +2634,14 @@ CREATE TABLE [dbo].[infra_file] ( | ||
| 2634 | [config_id] bigint NULL, | 2634 | [config_id] bigint NULL, |
| 2635 | [path] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | 2635 | [path] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, |
| 2636 | [url] nvarchar(1024) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | 2636 | [url] nvarchar(1024) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, |
| 2637 | - [type] nvarchar(63) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, | 2637 | + [type] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, |
| 2638 | [size] int NOT NULL, | 2638 | [size] int NOT NULL, |
| 2639 | [creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, | 2639 | [creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, |
| 2640 | [create_time] datetime2(7) NOT NULL, | 2640 | [create_time] datetime2(7) NOT NULL, |
| 2641 | [updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, | 2641 | [updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, |
| 2642 | [update_time] datetime2(7) NOT NULL, | 2642 | [update_time] datetime2(7) NOT NULL, |
| 2643 | [deleted] bit DEFAULT 0 NOT NULL, | 2643 | [deleted] bit DEFAULT 0 NOT NULL, |
| 2644 | - [name] nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL | 2644 | + [name] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NULL |
| 2645 | ) | 2645 | ) |
| 2646 | GO | 2646 | GO |
| 2647 | 2647 | ||
| @@ -2677,7 +2677,7 @@ EXEC sp_addextendedproperty | @@ -2677,7 +2677,7 @@ EXEC sp_addextendedproperty | ||
| 2677 | GO | 2677 | GO |
| 2678 | 2678 | ||
| 2679 | EXEC sp_addextendedproperty | 2679 | EXEC sp_addextendedproperty |
| 2680 | -'MS_Description', N'文件类型', | 2680 | +'MS_Description', N'文件 MIME 类型', |
| 2681 | 'SCHEMA', N'dbo', | 2681 | 'SCHEMA', N'dbo', |
| 2682 | 'TABLE', N'infra_file', | 2682 | 'TABLE', N'infra_file', |
| 2683 | 'COLUMN', N'type' | 2683 | 'COLUMN', N'type' |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/io/FileUtils.java
| 1 | package cn.iocoder.yudao.framework.common.util.io; | 1 | package cn.iocoder.yudao.framework.common.util.io; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.io.FileTypeUtil; | ||
| 3 | import cn.hutool.core.io.FileUtil; | 4 | import cn.hutool.core.io.FileUtil; |
| 5 | +import cn.hutool.core.io.file.FileNameUtil; | ||
| 4 | import cn.hutool.core.util.IdUtil; | 6 | import cn.hutool.core.util.IdUtil; |
| 7 | +import cn.hutool.core.util.StrUtil; | ||
| 8 | +import cn.hutool.crypto.digest.DigestUtil; | ||
| 5 | import lombok.SneakyThrows; | 9 | import lombok.SneakyThrows; |
| 6 | 10 | ||
| 11 | +import java.io.ByteArrayInputStream; | ||
| 7 | import java.io.File; | 12 | import java.io.File; |
| 8 | 13 | ||
| 9 | /** | 14 | /** |
| @@ -58,8 +63,20 @@ public class FileUtils { | @@ -58,8 +63,20 @@ public class FileUtils { | ||
| 58 | return file; | 63 | return file; |
| 59 | } | 64 | } |
| 60 | 65 | ||
| 61 | - | ||
| 62 | - public static void main(String[] args) { | 66 | + /** |
| 67 | + * @param content 文件内容 | ||
| 68 | + * @param originalName 原始文件名 | ||
| 69 | + * @return path,唯一不可重复 | ||
| 70 | + */ | ||
| 71 | + public static String generatePath(byte[] content, String originalName) { | ||
| 72 | + String sha256Hex = DigestUtil.sha256Hex(content); | ||
| 73 | + // 如果存在name,则优先使用name的后缀 | ||
| 74 | + if (StrUtil.isNotBlank(originalName)) { | ||
| 75 | + String extName = FileNameUtil.extName(originalName); | ||
| 76 | + return StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName; | ||
| 77 | + } else { | ||
| 78 | + return sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content)); | ||
| 79 | + } | ||
| 63 | } | 80 | } |
| 64 | 81 | ||
| 65 | } | 82 | } |
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; | @@ -4,8 +4,6 @@ import com.alibaba.ttl.TransmittableThreadLocal; | ||
| 4 | import lombok.SneakyThrows; | 4 | import lombok.SneakyThrows; |
| 5 | import org.apache.tika.Tika; | 5 | import org.apache.tika.Tika; |
| 6 | 6 | ||
| 7 | -import java.io.ByteArrayInputStream; | ||
| 8 | - | ||
| 9 | /** | 7 | /** |
| 10 | * 文件类型 Utils | 8 | * 文件类型 Utils |
| 11 | * | 9 | * |
| @@ -16,14 +14,35 @@ public class FileTypeUtils { | @@ -16,14 +14,35 @@ public class FileTypeUtils { | ||
| 16 | private static final ThreadLocal<Tika> TIKA = TransmittableThreadLocal.withInitial(Tika::new); | 14 | private static final ThreadLocal<Tika> TIKA = TransmittableThreadLocal.withInitial(Tika::new); |
| 17 | 15 | ||
| 18 | /** | 16 | /** |
| 19 | - * 获得文件的 mineType | 17 | + * 获得文件的 mineType,对于doc,jar等文件会有误差 |
| 20 | * | 18 | * |
| 21 | * @param data 文件内容 | 19 | * @param data 文件内容 |
| 22 | - * @return mineType | 20 | + * @return mineType 无法识别时会返回“application/octet-stream” |
| 23 | */ | 21 | */ |
| 24 | @SneakyThrows | 22 | @SneakyThrows |
| 25 | public static String getMineType(byte[] data) { | 23 | public static String getMineType(byte[] data) { |
| 26 | - return TIKA.get().detect(new ByteArrayInputStream(data)); | 24 | + return TIKA.get().detect(data); |
| 25 | + } | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 已知文件名,获取文件类型,在某些情况下比通过字节数组准确,例如使用jar文件时,通过名字更为准确 | ||
| 29 | + * | ||
| 30 | + * @param name 文件名 | ||
| 31 | + * @return mineType 无法识别时会返回“application/octet-stream” | ||
| 32 | + */ | ||
| 33 | + public static String getMineType(String name) { | ||
| 34 | + return TIKA.get().detect(name); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 在拥有文件和数据的情况下,最好使用此方法,最为准确 | ||
| 39 | + * | ||
| 40 | + * @param data 文件内容 | ||
| 41 | + * @param name 文件名 | ||
| 42 | + * @return mineType 无法识别时会返回“application/octet-stream” | ||
| 43 | + */ | ||
| 44 | + public static String getMineType(byte[] data, String name) { | ||
| 45 | + return TIKA.get().detect(data, name); | ||
| 27 | } | 46 | } |
| 28 | 47 | ||
| 29 | } | 48 | } |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePageReqVO.java
| @@ -21,7 +21,7 @@ public class FilePageReqVO extends PageParam { | @@ -21,7 +21,7 @@ public class FilePageReqVO extends PageParam { | ||
| 21 | @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配") | 21 | @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配") |
| 22 | private String path; | 22 | private String path; |
| 23 | 23 | ||
| 24 | - @ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配") | 24 | + @ApiModelProperty(value = "文件类型", example = "application/octet-stream", notes = "模糊匹配") |
| 25 | private String type; | 25 | private String type; |
| 26 | 26 | ||
| 27 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 27 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
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 { | @@ -13,6 +13,9 @@ public class FileRespVO { | ||
| 13 | @ApiModelProperty(value = "文件编号", required = true, example = "1024") | 13 | @ApiModelProperty(value = "文件编号", required = true, example = "1024") |
| 14 | private Long id; | 14 | private Long id; |
| 15 | 15 | ||
| 16 | + @ApiModelProperty(value = "配置编号", required = true, example = "11") | ||
| 17 | + private Long configId; | ||
| 18 | + | ||
| 16 | @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg") | 19 | @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg") |
| 17 | private String path; | 20 | private String path; |
| 18 | 21 | ||
| @@ -22,7 +25,7 @@ public class FileRespVO { | @@ -22,7 +25,7 @@ public class FileRespVO { | ||
| 22 | @ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg") | 25 | @ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg") |
| 23 | private String url; | 26 | private String url; |
| 24 | 27 | ||
| 25 | - @ApiModelProperty(value = "文件类型", example = "jpg") | 28 | + @ApiModelProperty(value = "文件MIME类型", example = "application/octet-stream") |
| 26 | private String type; | 29 | private String type; |
| 27 | 30 | ||
| 28 | @ApiModelProperty(value = "文件大小", example = "2048", required = true) | 31 | @ApiModelProperty(value = "文件大小", example = "2048", required = true) |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java
| @@ -46,9 +46,7 @@ public class FileDO extends BaseDO { | @@ -46,9 +46,7 @@ public class FileDO extends BaseDO { | ||
| 46 | */ | 46 | */ |
| 47 | private String url; | 47 | private String url; |
| 48 | /** | 48 | /** |
| 49 | - * 文件类型 | ||
| 50 | - * | ||
| 51 | - * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取 | 49 | + * 文件的MIME类型,例如"application/octet-stream" |
| 52 | */ | 50 | */ |
| 53 | private String type; | 51 | private String type; |
| 54 | /** | 52 | /** |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
| 1 | package cn.iocoder.yudao.module.infra.service.file; | 1 | package cn.iocoder.yudao.module.infra.service.file; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.io.FileUtil; | ||
| 3 | import cn.hutool.core.lang.Assert; | 4 | import cn.hutool.core.lang.Assert; |
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.hutool.crypto.digest.DigestUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.common.util.io.FileUtils; | ||
| 7 | import cn.iocoder.yudao.framework.file.core.client.FileClient; | 8 | import cn.iocoder.yudao.framework.file.core.client.FileClient; |
| 8 | import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; | 9 | import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; |
| 9 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; | 10 | import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; |
| @@ -40,10 +41,9 @@ public class FileServiceImpl implements FileService { | @@ -40,10 +41,9 @@ public class FileServiceImpl implements FileService { | ||
| 40 | @SneakyThrows | 41 | @SneakyThrows |
| 41 | public String createFile(String name, String path, byte[] content) { | 42 | public String createFile(String name, String path, byte[] content) { |
| 42 | // 计算默认的 path 名 | 43 | // 计算默认的 path 名 |
| 43 | - String type = FileTypeUtils.getMineType(content); | 44 | + String type = FileTypeUtils.getMineType(content, name); |
| 44 | if (StrUtil.isEmpty(path)) { | 45 | if (StrUtil.isEmpty(path)) { |
| 45 | - path = DigestUtil.md5Hex(content) | ||
| 46 | - + '.' + StrUtil.subAfter(type, '/', true); // 文件的后缀 | 46 | + path = FileUtils.generatePath(content, name); |
| 47 | } | 47 | } |
| 48 | // 如果 name 为空,则使用 path 填充 | 48 | // 如果 name 为空,则使用 path 填充 |
| 49 | if (StrUtil.isEmpty(name)) { | 49 | if (StrUtil.isEmpty(name)) { |
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java
| @@ -40,7 +40,7 @@ public class FileServiceTest extends BaseDbUnitTest { | @@ -40,7 +40,7 @@ public class FileServiceTest extends BaseDbUnitTest { | ||
| 40 | // mock 数据 | 40 | // mock 数据 |
| 41 | FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到 | 41 | FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到 |
| 42 | o.setPath("yunai"); | 42 | o.setPath("yunai"); |
| 43 | - o.setType("jpg"); | 43 | + o.setType("image/jpg"); |
| 44 | o.setCreateTime(buildTime(2021, 1, 15)); | 44 | o.setCreateTime(buildTime(2021, 1, 15)); |
| 45 | }); | 45 | }); |
| 46 | fileMapper.insert(dbFile); | 46 | fileMapper.insert(dbFile); |
| @@ -48,7 +48,7 @@ public class FileServiceTest extends BaseDbUnitTest { | @@ -48,7 +48,7 @@ public class FileServiceTest extends BaseDbUnitTest { | ||
| 48 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou"))); | 48 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou"))); |
| 49 | // 测试 type 不匹配 | 49 | // 测试 type 不匹配 |
| 50 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { | 50 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { |
| 51 | - o.setType("png"); | 51 | + o.setType("image/png"); |
| 52 | })); | 52 | })); |
| 53 | // 测试 createTime 不匹配 | 53 | // 测试 createTime 不匹配 |
| 54 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { | 54 | fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { |
| @@ -90,7 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest { | @@ -90,7 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest { | ||
| 90 | assertEquals(10L, file.getConfigId()); | 90 | assertEquals(10L, file.getConfigId()); |
| 91 | assertEquals(path, file.getPath()); | 91 | assertEquals(path, file.getPath()); |
| 92 | assertEquals(url, file.getUrl()); | 92 | assertEquals(url, file.getUrl()); |
| 93 | - assertEquals("jpg", file.getType()); | 93 | + assertEquals("image/jpg", file.getType()); |
| 94 | assertEquals(content.length, file.getSize()); | 94 | assertEquals(content.length, file.getSize()); |
| 95 | } | 95 | } |
| 96 | 96 |
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; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | import com.baomidou.mybatisplus.annotation.KeySequence; | 5 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 6 | import com.baomidou.mybatisplus.annotation.TableName; | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | import lombok.*; | 8 | import lombok.*; |
| 8 | 9 | ||
| @@ -22,6 +23,11 @@ import lombok.*; | @@ -22,6 +23,11 @@ import lombok.*; | ||
| 22 | public class SocialUserBindDO extends BaseDO { | 23 | public class SocialUserBindDO extends BaseDO { |
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| 26 | + * 编号 | ||
| 27 | + */ | ||
| 28 | + @TableId | ||
| 29 | + private Long id; | ||
| 30 | + /** | ||
| 25 | * 关联的用户编号 | 31 | * 关联的用户编号 |
| 26 | * | 32 | * |
| 27 | * 关联 UserDO 的编号 | 33 | * 关联 UserDO 的编号 |
yudao-ui-admin/src/views/infra/file/index.vue
| @@ -26,27 +26,32 @@ | @@ -26,27 +26,32 @@ | ||
| 26 | 26 | ||
| 27 | <!-- 列表 --> | 27 | <!-- 列表 --> |
| 28 | <el-table v-loading="loading" :data="list"> | 28 | <el-table v-loading="loading" :data="list"> |
| 29 | - <el-table-column label="文件名" align="center" prop="name" /> | ||
| 30 | - <el-table-column label="文件路径" align="center" prop="path" /> | ||
| 31 | - <el-table-column label="文件 URL" align="center" prop="url" /> | ||
| 32 | - <el-table-column label="文件大小" align="center" prop="size" width="120" :formatter="sizeFormat" /> | ||
| 33 | - <el-table-column label="文件类型" align="center" prop="type" width="80" /> | ||
| 34 | -<!-- <el-table-column label="文件内容" align="center" prop="content">--> | ||
| 35 | -<!-- <template slot-scope="scope">--> | ||
| 36 | -<!-- <img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'"--> | ||
| 37 | -<!-- width="200px" :src="getFileUrl + scope.row.id">--> | ||
| 38 | -<!-- <i v-else>非图片,无法预览</i>--> | ||
| 39 | -<!-- </template>--> | ||
| 40 | -<!-- </el-table-column>--> | ||
| 41 | - <el-table-column label="上传时间" align="center" prop="createTime" width="180"> | 29 | + <el-table-column label="文件名" :show-overflow-tooltip="true" align="center" min-width="200px" prop="name"/> |
| 30 | + <el-table-column label="文件路径" :show-overflow-tooltip="true" align="center" min-width="250px" prop="path"/> | ||
| 31 | + <el-table-column label="文件 URL" :show-overflow-tooltip="true" align="center" min-width="300px" prop="url"/> | ||
| 32 | + <el-table-column label="文件大小" align="center" prop="size" min-width="120px" :formatter="sizeFormat"/> | ||
| 33 | + <el-table-column label="文件类型" :show-overflow-tooltip="true" align="center" prop="type" width="180px"/> | ||
| 34 | + <el-table-column label="文件内容" align="center" prop="content" min-width="150px"> | ||
| 35 | + <template slot-scope="scope"> | ||
| 36 | + <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url" | ||
| 37 | + :width="'100px'"></image-preview> | ||
| 38 | + <i v-else>无法预览,点击 | ||
| 39 | + <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" target="_blank" | ||
| 40 | + :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载 | ||
| 41 | + </el-link> | ||
| 42 | + </i> | ||
| 43 | + </template> | ||
| 44 | + </el-table-column> | ||
| 45 | + <el-table-column label="上传时间" align="center" prop="createTime" min-width="170px"> | ||
| 42 | <template slot-scope="scope"> | 46 | <template slot-scope="scope"> |
| 43 | <span>{{ parseTime(scope.row.createTime) }}</span> | 47 | <span>{{ parseTime(scope.row.createTime) }}</span> |
| 44 | </template> | 48 | </template> |
| 45 | </el-table-column> | 49 | </el-table-column> |
| 46 | - <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100"> | 50 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="100px"> |
| 47 | <template slot-scope="scope"> | 51 | <template slot-scope="scope"> |
| 48 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | 52 | <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" |
| 49 | - v-hasPermi="['infra:file:delete']">删除</el-button> | 53 | + v-hasPermi="['infra:file:delete']">删除 |
| 54 | + </el-button> | ||
| 50 | </template> | 55 | </template> |
| 51 | </el-table-column> | 56 | </el-table-column> |
| 52 | </el-table> | 57 | </el-table> |
| @@ -77,14 +82,18 @@ | @@ -77,14 +82,18 @@ | ||
| 77 | </template> | 82 | </template> |
| 78 | 83 | ||
| 79 | <script> | 84 | <script> |
| 80 | -import { deleteFile, getFilePage } from "@/api/infra/file"; | 85 | +import {deleteFile, getFilePage} from "@/api/infra/file"; |
| 81 | import {getAccessToken} from "@/utils/auth"; | 86 | import {getAccessToken} from "@/utils/auth"; |
| 87 | +import ImagePreview from "@/components/ImagePreview"; | ||
| 82 | 88 | ||
| 83 | export default { | 89 | export default { |
| 84 | name: "File", | 90 | name: "File", |
| 91 | + components: { | ||
| 92 | + ImagePreview | ||
| 93 | + }, | ||
| 85 | data() { | 94 | data() { |
| 86 | return { | 95 | return { |
| 87 | - getFileUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/get/', | 96 | + getFileUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/', |
| 88 | // 遮罩层 | 97 | // 遮罩层 |
| 89 | loading: true, | 98 | loading: true, |
| 90 | // 显示搜索条件 | 99 | // 显示搜索条件 |