mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-23 07:41:53 +08:00
1. 修改文件名和文件路径字段长度一致,因为如果不存在文件名的情况下,会使用文件路径作为字段名,防止数据库报错字段内容太长。
2. 修改type字段为ext_name,因为此字段本来就存的文件扩展名,并且新增mime_type字段,用来存储文件的类型。方便后期拓展网盘项目。 3. 修改文件路径生成方式:之前是md5,现在是sha256,降低文件碰撞概率。方便拓展网盘项目,实现秒传等功能。
This commit is contained in:
parent
d14ad888e2
commit
a68a979149
@ -689,10 +689,11 @@ DROP TABLE IF EXISTS `infra_file`;
|
|||||||
CREATE TABLE `infra_file` (
|
CREATE TABLE `infra_file` (
|
||||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号',
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '文件编号',
|
||||||
`config_id` bigint NULL DEFAULT NULL 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 '文件路径',
|
`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',
|
`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 '文件大小',
|
`size` int NOT NULL COMMENT '文件大小',
|
||||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
@ -878,7 +878,8 @@ CREATE TABLE "INFRA_FILE" (
|
|||||||
"CONFIG_ID" NUMBER(20,0),
|
"CONFIG_ID" NUMBER(20,0),
|
||||||
"PATH" NVARCHAR2(512),
|
"PATH" NVARCHAR2(512),
|
||||||
"URL" NCLOB,
|
"URL" NCLOB,
|
||||||
"TYPE" NVARCHAR2(63),
|
"EXT_NAME" NVARCHAR2(63),
|
||||||
|
"MIME_TYPE" NVARCHAR2(63),
|
||||||
"SIZE" NUMBER(11,0) NOT NULL,
|
"SIZE" NUMBER(11,0) NOT NULL,
|
||||||
"CREATOR" NVARCHAR2(64),
|
"CREATOR" NVARCHAR2(64),
|
||||||
"CREATE_TIME" DATE NOT NULL,
|
"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"."CONFIG_ID" IS '配置编号';
|
||||||
COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径';
|
COMMENT ON COLUMN "INFRA_FILE"."PATH" IS '文件路径';
|
||||||
COMMENT ON COLUMN "INFRA_FILE"."URL" IS '文件 URL';
|
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"."SIZE" IS '文件大小';
|
||||||
COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者';
|
COMMENT ON COLUMN "INFRA_FILE"."CREATOR" IS '创建者';
|
||||||
COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间';
|
COMMENT ON COLUMN "INFRA_FILE"."CREATE_TIME" IS '创建时间';
|
||||||
|
@ -1717,21 +1717,23 @@ CREATE TABLE "infra_file" (
|
|||||||
"config_id" int8,
|
"config_id" int8,
|
||||||
"path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
|
"path" varchar(512) COLLATE "pg_catalog"."default" NOT NULL,
|
||||||
"url" varchar(1024) 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,
|
"size" int4 NOT NULL,
|
||||||
"creator" varchar(64) COLLATE "pg_catalog"."default",
|
"creator" varchar(64) COLLATE "pg_catalog"."default",
|
||||||
"create_time" timestamp(6) NOT NULL,
|
"create_time" timestamp(6) NOT NULL,
|
||||||
"updater" varchar(64) COLLATE "pg_catalog"."default",
|
"updater" varchar(64) COLLATE "pg_catalog"."default",
|
||||||
"update_time" timestamp(6) NOT NULL,
|
"update_time" timestamp(6) NOT NULL,
|
||||||
"deleted" int2 NOT NULL DEFAULT 0,
|
"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"."id" IS '文件编号';
|
||||||
COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号';
|
COMMENT ON COLUMN "infra_file"."config_id" IS '配置编号';
|
||||||
COMMENT ON COLUMN "infra_file"."path" IS '文件路径';
|
COMMENT ON COLUMN "infra_file"."path" IS '文件路径';
|
||||||
COMMENT ON COLUMN "infra_file"."url" IS '文件 URL';
|
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"."size" IS '文件大小';
|
||||||
COMMENT ON COLUMN "infra_file"."creator" IS '创建者';
|
COMMENT ON COLUMN "infra_file"."creator" IS '创建者';
|
||||||
COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间';
|
COMMENT ON COLUMN "infra_file"."create_time" IS '创建时间';
|
||||||
|
@ -2634,14 +2634,15 @@ CREATE TABLE [dbo].[infra_file] (
|
|||||||
[config_id] bigint NULL,
|
[config_id] bigint NULL,
|
||||||
[path] nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NOT 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,
|
[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,
|
[size] int NOT NULL,
|
||||||
[creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
[creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||||
[create_time] datetime2(7) NOT NULL,
|
[create_time] datetime2(7) NOT NULL,
|
||||||
[updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
[updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||||
[update_time] datetime2(7) NOT NULL,
|
[update_time] datetime2(7) NOT NULL,
|
||||||
[deleted] bit DEFAULT 0 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
|
GO
|
||||||
|
|
||||||
@ -2677,10 +2678,17 @@ EXEC sp_addextendedproperty
|
|||||||
GO
|
GO
|
||||||
|
|
||||||
EXEC sp_addextendedproperty
|
EXEC sp_addextendedproperty
|
||||||
'MS_Description', N'文件类型',
|
'MS_Description', N'文件扩展名',
|
||||||
'SCHEMA', N'dbo',
|
'SCHEMA', N'dbo',
|
||||||
'TABLE', N'infra_file',
|
'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
|
GO
|
||||||
|
|
||||||
EXEC sp_addextendedproperty
|
EXEC sp_addextendedproperty
|
||||||
|
@ -14,7 +14,7 @@ public interface FileApi {
|
|||||||
* @return 文件路径
|
* @return 文件路径
|
||||||
*/
|
*/
|
||||||
default String createFile(byte[] content) {
|
default String createFile(byte[] content) {
|
||||||
return createFile(null, null, content);
|
return createFile(null, null, "application/octet-stream", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +25,7 @@ public interface FileApi {
|
|||||||
* @return 文件路径
|
* @return 文件路径
|
||||||
*/
|
*/
|
||||||
default String createFile(String path, byte[] content) {
|
default String createFile(String path, byte[] content) {
|
||||||
return createFile(null, path, content);
|
return createFile(null, path, "application/octet-stream", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,9 +33,10 @@ public interface FileApi {
|
|||||||
*
|
*
|
||||||
* @param name 文件名称
|
* @param name 文件名称
|
||||||
* @param path 文件路径
|
* @param path 文件路径
|
||||||
|
* @param mimeType 文件类型
|
||||||
* @param content 文件内容
|
* @param content 文件内容
|
||||||
* @return 文件路径
|
* @return 文件路径
|
||||||
*/
|
*/
|
||||||
String createFile(String name, String path, byte[] content);
|
String createFile(String name, String path, String mimeType, byte[] content);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ public class FileApiImpl implements FileApi {
|
|||||||
private FileService fileService;
|
private FileService fileService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createFile(String name, String path, byte[] content) {
|
public String createFile(String name, String path, String mimeType, byte[] content) {
|
||||||
return fileService.createFile(name, path, content);
|
return fileService.createFile(name, path, mimeType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class FileController {
|
|||||||
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
|
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
|
||||||
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
||||||
@RequestParam(value = "path", required = false) String path) throws Exception {
|
@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")
|
@DeleteMapping("/delete")
|
||||||
|
@ -38,7 +38,7 @@ public class FileDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
/**
|
||||||
* 路径,即文件名
|
* 路径,即文件名,唯一不可重复
|
||||||
*/
|
*/
|
||||||
private String path;
|
private String path;
|
||||||
/**
|
/**
|
||||||
@ -46,11 +46,15 @@ public class FileDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private String url;
|
private String url;
|
||||||
/**
|
/**
|
||||||
* 文件类型
|
* 文件扩展名
|
||||||
*
|
* <p>
|
||||||
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
|
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
|
||||||
*/
|
*/
|
||||||
private String type;
|
private String extName;
|
||||||
|
/**
|
||||||
|
* 文件的MIME类型,默认为"application/octet-stream"
|
||||||
|
*/
|
||||||
|
private String mimeType;
|
||||||
/**
|
/**
|
||||||
* 文件大小
|
* 文件大小
|
||||||
*/
|
*/
|
||||||
|
@ -24,10 +24,11 @@ public interface FileService {
|
|||||||
*
|
*
|
||||||
* @param name 文件名称
|
* @param name 文件名称
|
||||||
* @param path 文件路径
|
* @param path 文件路径
|
||||||
|
* @param mimeType 文件MIME类型
|
||||||
* @param content 文件内容
|
* @param content 文件内容
|
||||||
* @return 文件路径
|
* @return 文件路径
|
||||||
*/
|
*/
|
||||||
String createFile(String name, String path, byte[] content);
|
String createFile(String name, String path, String mimeType,byte[] content);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除文件
|
* 删除文件
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.infra.service.file;
|
package cn.iocoder.yudao.module.infra.service.file;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileTypeUtil;
|
import cn.hutool.core.io.FileTypeUtil;
|
||||||
|
import cn.hutool.core.io.file.FileNameUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
@ -39,11 +40,13 @@ public class FileServiceImpl implements FileService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String createFile(String name, String path, byte[] content) {
|
public String createFile(String name, String path, String mimeType, byte[] content) {
|
||||||
// 计算默认的 path 名
|
//获取文件的真实扩展名
|
||||||
String type = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
|
String extName = FileTypeUtil.getType(new ByteArrayInputStream(content), name);
|
||||||
|
FileNameUtil.extName(name);
|
||||||
if (StrUtil.isEmpty(path)) {
|
if (StrUtil.isEmpty(path)) {
|
||||||
path = DigestUtil.md5Hex(content) + '.' + type;
|
//使用sha256计算文件都唯一路径,降低碰撞概率
|
||||||
|
path = DigestUtil.sha256Hex(content) + '.' + extName;
|
||||||
}
|
}
|
||||||
// 如果 name 为空,则使用 path 填充
|
// 如果 name 为空,则使用 path 填充
|
||||||
if (StrUtil.isEmpty(name)) {
|
if (StrUtil.isEmpty(name)) {
|
||||||
@ -61,7 +64,8 @@ public class FileServiceImpl implements FileService {
|
|||||||
file.setName(name);
|
file.setName(name);
|
||||||
file.setPath(path);
|
file.setPath(path);
|
||||||
file.setUrl(url);
|
file.setUrl(url);
|
||||||
file.setType(type);
|
file.setExtName(extName);
|
||||||
|
file.setMimeType(mimeType);
|
||||||
file.setSize(content.length);
|
file.setSize(content.length);
|
||||||
fileMapper.insert(file);
|
fileMapper.insert(file);
|
||||||
return url;
|
return url;
|
||||||
|
@ -40,7 +40,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
|||||||
// mock 数据
|
// mock 数据
|
||||||
FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
|
FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到
|
||||||
o.setPath("yunai");
|
o.setPath("yunai");
|
||||||
o.setType("jpg");
|
o.setExtName("jpg");
|
||||||
o.setCreateTime(buildTime(2021, 1, 15));
|
o.setCreateTime(buildTime(2021, 1, 15));
|
||||||
});
|
});
|
||||||
fileMapper.insert(dbFile);
|
fileMapper.insert(dbFile);
|
||||||
@ -48,7 +48,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
|||||||
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
|
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setPath("tudou")));
|
||||||
// 测试 type 不匹配
|
// 测试 type 不匹配
|
||||||
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
|
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
|
||||||
o.setType("png");
|
o.setExtName("png");
|
||||||
}));
|
}));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
|
fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
|
||||||
@ -82,7 +82,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
|||||||
when(client.getId()).thenReturn(10L);
|
when(client.getId()).thenReturn(10L);
|
||||||
String name = "单测文件名";
|
String name = "单测文件名";
|
||||||
// 调用
|
// 调用
|
||||||
String result = fileService.createFile(name, path, content);
|
String result = fileService.createFile(name, path, "application/octet-stream", content);
|
||||||
// 断言
|
// 断言
|
||||||
assertEquals(result, url);
|
assertEquals(result, url);
|
||||||
// 校验数据
|
// 校验数据
|
||||||
@ -90,7 +90,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
|||||||
assertEquals(10L, file.getConfigId());
|
assertEquals(10L, file.getConfigId());
|
||||||
assertEquals(path, file.getPath());
|
assertEquals(path, file.getPath());
|
||||||
assertEquals(url, file.getUrl());
|
assertEquals(url, file.getUrl());
|
||||||
assertEquals("jpg", file.getType());
|
assertEquals("jpg", file.getExtName());
|
||||||
assertEquals(content.length, file.getSize());
|
assertEquals(content.length, file.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user