Commit 1c75665ae76d4a202914e4563841433f1209fd18
1 parent
60f13815
✨ feat(file): update file naming strategy to support timestamp as directory or suffix
Showing
2 changed files
with
71 additions
and
2 deletions
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
| @@ -47,7 +47,14 @@ public class FileServiceImpl implements FileService { | @@ -47,7 +47,14 @@ public class FileServiceImpl implements FileService { | ||
| 47 | * 目的:保证文件的唯一性,避免覆盖 | 47 | * 目的:保证文件的唯一性,避免覆盖 |
| 48 | * 定制:可按需调整成 UUID、或者其他方式 | 48 | * 定制:可按需调整成 UUID、或者其他方式 |
| 49 | */ | 49 | */ |
| 50 | - static boolean PATH_SUFFIX_TIMESTAMP_ENABLE = true; | 50 | + static boolean PATH_SUFFIX_TIMESTAMP_ENABLE = false; |
| 51 | + /** | ||
| 52 | + * 时间戳是否作为上级目录 | ||
| 53 | + * | ||
| 54 | + * true:{@code yyyyMMdd/timestamp/原文件名.ext};保留原文件名 | ||
| 55 | + * false:{@code yyyyMMdd/原文件名_timestamp.ext};时间戳拼到文件名 | ||
| 56 | + */ | ||
| 57 | + static boolean PATH_TIMESTAMP_AS_DIRECTORY = true; | ||
| 51 | 58 | ||
| 52 | @Resource | 59 | @Resource |
| 53 | private FileConfigService fileConfigService; | 60 | private FileConfigService fileConfigService; |
| @@ -102,12 +109,22 @@ public class FileServiceImpl implements FileService { | @@ -102,12 +109,22 @@ public class FileServiceImpl implements FileService { | ||
| 102 | } | 109 | } |
| 103 | String suffix = null; | 110 | String suffix = null; |
| 104 | if (PATH_SUFFIX_TIMESTAMP_ENABLE) { | 111 | if (PATH_SUFFIX_TIMESTAMP_ENABLE) { |
| 112 | + // 5 位随机数,避免同一毫秒内的重复 | ||
| 105 | suffix = String.valueOf(System.currentTimeMillis()) + RandomUtil.randomInt(10000, 100000); | 113 | suffix = String.valueOf(System.currentTimeMillis()) + RandomUtil.randomInt(10000, 100000); |
| 106 | } | 114 | } |
| 107 | 115 | ||
| 108 | // 2.1 先拼接 suffix 后缀 | 116 | // 2.1 先拼接 suffix 后缀 |
| 109 | if (StrUtil.isNotEmpty(suffix)) { | 117 | if (StrUtil.isNotEmpty(suffix)) { |
| 110 | - name = suffix + StrUtil.SLASH + name; | 118 | + if (PATH_TIMESTAMP_AS_DIRECTORY) { |
| 119 | + name = suffix + StrUtil.SLASH + name; | ||
| 120 | + } else { | ||
| 121 | + String ext = FileUtil.extName(name); | ||
| 122 | + if (StrUtil.isNotEmpty(ext)) { | ||
| 123 | + name = FileUtil.mainName(name) + StrUtil.C_UNDERLINE + suffix + StrUtil.DOT + ext; | ||
| 124 | + } else { | ||
| 125 | + name = name + StrUtil.C_UNDERLINE + suffix; | ||
| 126 | + } | ||
| 127 | + } | ||
| 111 | } | 128 | } |
| 112 | // 2.2 再拼接 prefix 前缀 | 129 | // 2.2 再拼接 prefix 前缀 |
| 113 | if (StrUtil.isNotEmpty(prefix)) { | 130 | if (StrUtil.isNotEmpty(prefix)) { |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImplTest.java
| @@ -42,6 +42,7 @@ public class FileServiceImplTest extends BaseDbUnitTest { | @@ -42,6 +42,7 @@ public class FileServiceImplTest extends BaseDbUnitTest { | ||
| 42 | public void setUp() { | 42 | public void setUp() { |
| 43 | FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true; | 43 | FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true; |
| 44 | FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true; | 44 | FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true; |
| 45 | + FileServiceImpl.PATH_TIMESTAMP_AS_DIRECTORY = true; | ||
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | @Test | 48 | @Test |
| @@ -291,6 +292,57 @@ public class FileServiceImplTest extends BaseDbUnitTest { | @@ -291,6 +292,57 @@ public class FileServiceImplTest extends BaseDbUnitTest { | ||
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | @Test | 294 | @Test |
| 295 | + public void testGenerateUploadPath_TimestampAsName_AllEnabled() { | ||
| 296 | + // 准备参数 | ||
| 297 | + String name = "test.jpg"; | ||
| 298 | + String directory = "avatar"; | ||
| 299 | + FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true; | ||
| 300 | + FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true; | ||
| 301 | + FileServiceImpl.PATH_TIMESTAMP_AS_DIRECTORY = false; | ||
| 302 | + | ||
| 303 | + // 调用 | ||
| 304 | + String path = fileService.generateUploadPath(name, directory); | ||
| 305 | + | ||
| 306 | + // 断言 | ||
| 307 | + // 格式为:avatar/yyyyMMdd/test_timestamp.jpg | ||
| 308 | + assertTrue(path.matches(directory + "/\\d{8}/test_\\d+\\.jpg")); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + @Test | ||
| 312 | + public void testGenerateUploadPath_TimestampAsName_PrefixDisabled() { | ||
| 313 | + // 准备参数 | ||
| 314 | + String name = "test.jpg"; | ||
| 315 | + String directory = "avatar"; | ||
| 316 | + FileServiceImpl.PATH_PREFIX_DATE_ENABLE = false; | ||
| 317 | + FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true; | ||
| 318 | + FileServiceImpl.PATH_TIMESTAMP_AS_DIRECTORY = false; | ||
| 319 | + | ||
| 320 | + // 调用 | ||
| 321 | + String path = fileService.generateUploadPath(name, directory); | ||
| 322 | + | ||
| 323 | + // 断言 | ||
| 324 | + // 格式为:avatar/test_timestamp.jpg | ||
| 325 | + assertTrue(path.matches(directory + "/test_\\d+\\.jpg")); | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + @Test | ||
| 329 | + public void testGenerateUploadPath_TimestampAsName_NoExtension() { | ||
| 330 | + // 准备参数 | ||
| 331 | + String name = "test"; | ||
| 332 | + String directory = "avatar"; | ||
| 333 | + FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true; | ||
| 334 | + FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true; | ||
| 335 | + FileServiceImpl.PATH_TIMESTAMP_AS_DIRECTORY = false; | ||
| 336 | + | ||
| 337 | + // 调用 | ||
| 338 | + String path = fileService.generateUploadPath(name, directory); | ||
| 339 | + | ||
| 340 | + // 断言 | ||
| 341 | + // 格式为:avatar/yyyyMMdd/test_timestamp | ||
| 342 | + assertTrue(path.matches(directory + "/\\d{8}/test_\\d+")); | ||
| 343 | + } | ||
| 344 | + | ||
| 345 | + @Test | ||
| 294 | public void testGenerateUploadPath_DirectoryEmpty() { | 346 | public void testGenerateUploadPath_DirectoryEmpty() { |
| 295 | // 准备参数 | 347 | // 准备参数 |
| 296 | String name = "test.jpg"; | 348 | String name = "test.jpg"; |