Jay
2024-10-09 41aaa0cc7c5fe00724be8fa44764a1fbc0c46dc9
提交 | 用户 | 时间
e7c126 1 package com.iailab.module.infra.framework.file.core.utils;
H 2
3 import cn.hutool.core.io.IoUtil;
4 import cn.hutool.core.util.StrUtil;
5 import com.alibaba.ttl.TransmittableThreadLocal;
6 import lombok.SneakyThrows;
7 import org.apache.tika.Tika;
8
9 import javax.servlet.http.HttpServletResponse;
10 import java.io.IOException;
11 import java.net.URLEncoder;
12
13 /**
14  * 文件类型 Utils
15  *
16  * @author iailab
17  */
18 public class FileTypeUtils {
19
20     private static final ThreadLocal<Tika> TIKA = TransmittableThreadLocal.withInitial(Tika::new);
21
22     /**
23      * 获得文件的 mineType,对于doc,jar等文件会有误差
24      *
25      * @param data 文件内容
26      * @return mineType 无法识别时会返回“application/octet-stream”
27      */
28     @SneakyThrows
29     public static String getMineType(byte[] data) {
30         return TIKA.get().detect(data);
31     }
32
33     /**
34      * 已知文件名,获取文件类型,在某些情况下比通过字节数组准确,例如使用jar文件时,通过名字更为准确
35      *
36      * @param name 文件名
37      * @return mineType 无法识别时会返回“application/octet-stream”
38      */
39     public static String getMineType(String name) {
40         return TIKA.get().detect(name);
41     }
42
43     /**
44      * 在拥有文件和数据的情况下,最好使用此方法,最为准确
45      *
46      * @param data 文件内容
47      * @param name 文件名
48      * @return mineType 无法识别时会返回“application/octet-stream”
49      */
50     public static String getMineType(byte[] data, String name) {
51         return TIKA.get().detect(data, name);
52     }
53
54     /**
55      * 返回附件
56      *
57      * @param response 响应
58      * @param filename 文件名
59      * @param content  附件内容
60      */
61     public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
62         // 设置 header 和 contentType
63         response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
64         String contentType = getMineType(content, filename);
65         response.setContentType(contentType);
66         // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题
67         if (StrUtil.containsIgnoreCase(contentType, "video")) {
68             response.setHeader("Content-Length", String.valueOf(content.length - 1));
69             response.setHeader("Content-Range", String.valueOf(content.length - 1));
70             response.setHeader("Accept-Ranges", "bytes");
71         }
72         // 输出附件
73         IoUtil.write(response.getOutputStream(), false, content);
74     }
75
76 }