Sfoglia il codice sorgente

优化获取mimetype方式,优化生成path方式

jiangqiang 2 anni fa
parent
commit
a5d16c11e8

+ 25 - 6
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);
     }
 
 }

+ 12 - 3
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)) {