判断文件类型一般可采用两种方式
后缀名判断
简单易操作,但无法准确判断类型
文件头信息判断
通常可以判断文件类型,但有些文件类型无法判断(如word和excel头信息的前几个字节是一样的,无法判断)
Apache Tika 是什么?
- Apache Tika用于文件类型检测和从各种格式的文件内容提取的库。
在内部,Tika使用现有的各种文件解析器和文档类型的检测技术来检测和提取数据。
- 使用Tika,人们可以开发出通用型检测器和内容提取到的不同类型的文件,如电子表格,文本文件,图像,PDF文件甚至多媒体输入格式,在一定程度上提取结构化文本以及元数据。
- Tika提供用于解析不同文件格式的一个通用API。它采用83个现有的专业解析器库,为每个文档类型。
- 所有这些解析器库是根据一个叫做Parser接口单一接口封装。
Tika类型检测
Tika支持MIME所提供的所有互联网媒体文件类型。每当一个文件通过Tika检测到该文件,其文件类型。检测的介质类型,Tika内部通过以下机制。
MIME标准
多用途Internet邮件扩展(MIME)标准,用于识别文件类型的最佳标准。这些标准的知识有助于在内部相互作用的浏览器。
当浏览器遇到一个媒体文件,它选择可用它来显示其内容的兼容软件。在情况下,它不具有任何合适的应用程序,以运行一个特定媒体文件,它建议用户获得合适的插件软件。
springboot 中使用
引入依赖
<!-- 上传文件验证 -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.9</version>
</dependency>
文件类型判断工具类
package com.cloudDisk.utils.file;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.HttpHeaders;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author 成大事
* @date 2021-12-20
*/
public class FileTypeJudge {
/**
* 获取类型
* @param multipartFile 文件
* @return mineType
*/
public static String getMimeTypeFile(MultipartFile multipartFile) throws Exception {
File file = MultipartFileToFile.multipartFileToFile(multipartFile);
if (file.isDirectory()) {
return "the target is a directory";
}
//创建自动检测解析器
AutoDetectParser parser = new AutoDetectParser();
parser.setParsers(new HashMap<MediaType, Parser>());
Metadata metadata = new Metadata();
metadata.add(TikaMetadataKeys.RESOURCE_NAME_KEY, file.getName());
InputStream stream;
try {
stream = new FileInputStream(file);
parser.parse(stream, new DefaultHandler(), metadata, new ParseContext());
stream.close();
} catch (TikaException | SAXException | IOException e) {
e.printStackTrace();
}
//将产生的临时文件删除
MultipartFileToFile.deleteTempFile(file);
return metadata.get(HttpHeaders.CONTENT_TYPE);
}
}
类型转换工具类
一般情况下,都是通过multipleFile来接收文件。但是tika是判断file 的。所以需要一个工具类将multiplefile转成file
package com.cloudDisk.utils.file;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author 成大事
* @since 2022/5/11 10:20
*/
public class MultipartFileToFile {
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除本地临时文件
* @param file
*/
public static void deleteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
}
测试
@GetMapping("/testUpload")
public R testUpload(
@RequestParam("file") MultipartFile file
) throws Exception {
String mimeType = FileTypeJudge.getMimeTypeFile(file);
log.info("tika 的格式{}",mimeType);
return R.ok(mimeType);
}
使用apiPost 测试发送文件
查看:
残留问题
就是不能直接对multiplefile的类型进行判断,得先转换成file的类型。之前参考的一篇博客
https://blog.csdn.net/weixin_43194885/article/details/109747552
可以实现简单的一些文件的判断。但是比如pptx,word还有xlsx都识别成application/zip。所以还是有问题。希望能解决的大佬可以帮忙指正修改一下。