|
|
@@ -11,13 +11,12 @@ import cn.hutool.core.util.StrUtil;
|
|
|
|
|
|
/**
|
|
|
* 文件类型判断工具类
|
|
|
- *
|
|
|
+ *
|
|
|
* <p>此工具根据文件的前几位bytes猜测文件类型,对于文本、zip判断不准确,对于视频、图片类型判断准确</p>
|
|
|
- *
|
|
|
+ *
|
|
|
* <p>需要注意的是,xlsx、docx等Office2007格式,全部识别为zip,因为新版采用了OpenXML格式,这些格式本质上是XML文件打包为zip</p>
|
|
|
- *
|
|
|
- * @author Looly
|
|
|
*
|
|
|
+ * @author Looly
|
|
|
*/
|
|
|
public class FileTypeUtil {
|
|
|
|
|
|
@@ -38,7 +37,6 @@ public class FileTypeUtil {
|
|
|
fileTypeMap.put("7b5c727466315c616e73", "rtf"); // Rich Text Format (rtf)
|
|
|
fileTypeMap.put("38425053000100000000", "psd"); // Photoshop (psd)
|
|
|
fileTypeMap.put("46726f6d3a203d3f6762", "eml"); // Email [Outlook Express 6] (eml)
|
|
|
- fileTypeMap.put("d0cf11e0a1b11ae10000", "doc"); // MS Excel 注意:word、msi 和 excel的文件头一样
|
|
|
fileTypeMap.put("5374616E64617264204A", "mdb"); // MS Access (mdb)
|
|
|
fileTypeMap.put("252150532D41646F6265", "ps");
|
|
|
fileTypeMap.put("255044462d312e", "pdf"); // Adobe Acrobat (pdf)
|
|
|
@@ -55,7 +53,8 @@ public class FileTypeUtil {
|
|
|
fileTypeMap.put("235468697320636f6e66", "ini");
|
|
|
fileTypeMap.put("504B03040a0000000000", "jar");
|
|
|
fileTypeMap.put("504B0304140008000800", "jar");
|
|
|
- fileTypeMap.put("D0CF11E0A1B11AE10", "xls");// xls文件
|
|
|
+ // MS Excel 注意:word、msi 和 excel的文件头一样
|
|
|
+ fileTypeMap.put("d0cf11e0a1b11ae10", "xls");
|
|
|
fileTypeMap.put("504B0304", "zip");
|
|
|
fileTypeMap.put("4d5a9000030000000400", "exe");// 可执行文件
|
|
|
fileTypeMap.put("3c25402070616765206c", "jsp");// jsp文件
|
|
|
@@ -79,9 +78,9 @@ public class FileTypeUtil {
|
|
|
/**
|
|
|
* 增加文件类型映射<br>
|
|
|
* 如果已经存在将覆盖之前的映射
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fileStreamHexHead 文件流头部Hex信息
|
|
|
- * @param extName 文件扩展名
|
|
|
+ * @param extName 文件扩展名
|
|
|
* @return 之前已经存在的文件扩展名
|
|
|
*/
|
|
|
public static String putFileType(String fileStreamHexHead, String extName) {
|
|
|
@@ -90,7 +89,7 @@ public class FileTypeUtil {
|
|
|
|
|
|
/**
|
|
|
* 移除文件类型映射
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fileStreamHexHead 文件流头部Hex信息
|
|
|
* @return 移除的文件扩展名
|
|
|
*/
|
|
|
@@ -100,13 +99,13 @@ public class FileTypeUtil {
|
|
|
|
|
|
/**
|
|
|
* 根据文件流的头部信息获得文件类型
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fileStreamHexHead 文件流头部16进制字符串
|
|
|
* @return 文件类型,未找到为<code>null</code>
|
|
|
*/
|
|
|
public static String getType(String fileStreamHexHead) {
|
|
|
for (Entry<String, String> fileTypeEntry : fileTypeMap.entrySet()) {
|
|
|
- if(StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
|
|
|
+ if (StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
|
|
|
return fileTypeEntry.getValue();
|
|
|
}
|
|
|
}
|
|
|
@@ -115,7 +114,7 @@ public class FileTypeUtil {
|
|
|
|
|
|
/**
|
|
|
* 根据文件流的头部信息获得文件类型
|
|
|
- *
|
|
|
+ *
|
|
|
* @param in {@link InputStream}
|
|
|
* @return 类型,文件的扩展名,未找到为<code>null</code>
|
|
|
* @throws IORuntimeException 读取流引起的异常
|
|
|
@@ -126,24 +125,59 @@ public class FileTypeUtil {
|
|
|
|
|
|
/**
|
|
|
* 根据文件流的头部信息获得文件类型
|
|
|
- *
|
|
|
+ *
|
|
|
+ * <pre>
|
|
|
+ * 1、无法识别类型默认按照扩展名识别
|
|
|
+ * 2、xls、doc、msi头信息无法区分,按照扩展名区分
|
|
|
+ * 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分
|
|
|
+ * </pre>
|
|
|
+ *
|
|
|
* @param file 文件 {@link File}
|
|
|
* @return 类型,文件的扩展名,未找到为<code>null</code>
|
|
|
* @throws IORuntimeException 读取文件引起的异常
|
|
|
*/
|
|
|
public static String getType(File file) throws IORuntimeException {
|
|
|
+ String typeName;
|
|
|
FileInputStream in = null;
|
|
|
try {
|
|
|
in = IoUtil.toStream(file);
|
|
|
- return getType(in);
|
|
|
+ typeName = getType(in);
|
|
|
} finally {
|
|
|
IoUtil.close(in);
|
|
|
}
|
|
|
+
|
|
|
+ if (null == typeName) {
|
|
|
+ // 未成功识别类型,扩展名辅助识别
|
|
|
+ typeName = FileUtil.extName(file);
|
|
|
+ } else if ("xls".equals(typeName)) {
|
|
|
+ // xls、doc、msi的头一样,使用扩展名辅助判断
|
|
|
+ final String extName = FileUtil.extName(file);
|
|
|
+ if ("doc".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "doc";
|
|
|
+ } else if ("msi".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "msi";
|
|
|
+ }
|
|
|
+ } else if ("zip".equals(typeName)) {
|
|
|
+ // zip可能为docx、xlsx、pptx、jar、war等格式,扩展名辅助判断
|
|
|
+ final String extName = FileUtil.extName(file);
|
|
|
+ if ("docx".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "docx";
|
|
|
+ } else if ("xlsx".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "xlsx";
|
|
|
+ } else if ("pptx".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "pptx";
|
|
|
+ } else if ("jar".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "jar";
|
|
|
+ } else if ("war".equalsIgnoreCase(extName)) {
|
|
|
+ typeName = "war";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return typeName;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 通过路径获得文件类型
|
|
|
- *
|
|
|
+ *
|
|
|
* @param path 路径,绝对路径或相对ClassPath的路径
|
|
|
* @return 类型
|
|
|
* @throws IORuntimeException 读取文件引起的异常
|