Commit a5d16c11e8a63db84ff9597f9807e9c3d914ccf8
1 parent
c64295f4
优化获取mimetype方式,优化生成path方式
Showing
2 changed files
with
37 additions
and
9 deletions
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 文件内容 | ||
| 22 | - * @return mineType | 19 | + * @param data 包含文件开头几千个字节的字节数组 |
| 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/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.FileTypeUtil; | ||
| 4 | +import cn.hutool.core.io.file.FileNameUtil; | ||
| 3 | import cn.hutool.core.lang.Assert; | 5 | import cn.hutool.core.lang.Assert; |
| 4 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.hutool.crypto.digest.DigestUtil; | 7 | import cn.hutool.crypto.digest.DigestUtil; |
| @@ -13,6 +15,7 @@ import lombok.SneakyThrows; | @@ -13,6 +15,7 @@ import lombok.SneakyThrows; | ||
| 13 | import org.springframework.stereotype.Service; | 15 | import org.springframework.stereotype.Service; |
| 14 | 16 | ||
| 15 | import javax.annotation.Resource; | 17 | import javax.annotation.Resource; |
| 18 | +import java.io.ByteArrayInputStream; | ||
| 16 | 19 | ||
| 17 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 18 | import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; | 21 | import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; |
| @@ -40,10 +43,16 @@ public class FileServiceImpl implements FileService { | @@ -40,10 +43,16 @@ public class FileServiceImpl implements FileService { | ||
| 40 | @SneakyThrows | 43 | @SneakyThrows |
| 41 | public String createFile(String name, String path, byte[] content) { | 44 | public String createFile(String name, String path, byte[] content) { |
| 42 | // 计算默认的 path 名 | 45 | // 计算默认的 path 名 |
| 43 | - String type = FileTypeUtils.getMineType(content); | 46 | + String type = FileTypeUtils.getMineType(content, name); |
| 44 | if (StrUtil.isEmpty(path)) { | 47 | if (StrUtil.isEmpty(path)) { |
| 45 | - path = DigestUtil.md5Hex(content) | ||
| 46 | - + '.' + StrUtil.subAfter(type, '/', true); // 文件的后缀 | 48 | + String sha256Hex = DigestUtil.sha256Hex(content); |
| 49 | + /* 如果存在name,则优先使用name的后缀 */ | ||
| 50 | + if (StrUtil.isNotBlank(name)) { | ||
| 51 | + String extName = FileNameUtil.extName(name); | ||
| 52 | + path = StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName; | ||
| 53 | + } else { | ||
| 54 | + path = sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content), name); | ||
| 55 | + } | ||
| 47 | } | 56 | } |
| 48 | // 如果 name 为空,则使用 path 填充 | 57 | // 如果 name 为空,则使用 path 填充 |
| 49 | if (StrUtil.isEmpty(name)) { | 58 | if (StrUtil.isEmpty(name)) { |