Java 获取文件的真实类型,修改后缀名也能识别出来
目录
前言
一、如何获取真实文件格式?
二、发开步骤
1. 定义枚举类,建立常见的文件类型与文件头魔数对应关系
2.新建GetFileTypeUtil工具类,获取文件格式
3.使用方法
总结
前言
今天在做文件上传下载的功能,前端需要我把文件转成base64编码给她。但是发现Java base64转码会缺失data数据,这样也就无法识别该文件是什么类型的,于是想写个工具类获取文件类型,追加上去。开始是想根据文件后缀名判断的,但这样要是故意修改文件后缀就无法准确判断了。在咨询一番度娘后,决定采用读取文件的十六进制文件头来判断文件的真正类型。
提示:以下是本篇文章正文内容,下面内容仅供个人学习记录,欢迎评论交流学习
一、如何获取真实文件格式?
当把文件的二进制数据转换成十六进制时,同类型文件的文件头数据是相同的,即使改变了其后缀,这个数据也不会改变。文件头是位于文件开头的一段承担一定任务的数据,一般在开头部分。头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序声明(declaration),而定义文件用于保存程序的实现(implementation)。一般文件头开始几节数据是固定的,被称为魔数,作为区分文件类型的硬添加进去的数据。(例如PNG格式的十六进制文件头数据就是以”89504E47″开头的,就可以判定该文件是PNG格式)为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断文件的真实类型。
二、发开步骤
1. 定义枚举类,建立常见的文件类型与文件头魔数对应关系
代码如下(示例):
package com.ruoyi.vip.fileLearn;
public enum FileType {
/**
* JEPG.
*/
JPEG("FFD8FF"),
/**
* PNG.
*/
PNG("89504E47"),
/**
* GIF.
*/
GIF("47494638"),
/**
* TIFF.
*/
TIFF("49492A00"),
TXT("6C657420"),
/**
* Windows Bitmap.
*/
BMP("424D"),
/**
* CAD.
*/
DWG("41433130"),
/**
* Adobe Photoshop.
*/
PSD("38425053"),
/**
* Rich Text Format.
*/
RTF("7B5C727466"),
/**
* XML.
*/
XML("3C3F786D6C"),
/**
* HTML.
*/
HTML("68746D6C3E"),
/**
* Email [thorough only].
*/
EML("44656C69766572792D646174653A"),
/**
* Outlook Express.
*/
DBX("CFAD12FEC5FD746F"),
/**
* Outlook (pst).
*/
PST("2142444E"),
/**
* MS Word/Excel.
*/
XLS_DOC("D0CF11E0"),
/**
* MS Access.
*/
MDB("5374616E64617264204A"),
/**
* WordPerfect.
*/
WPD("FF575043"),
/**
* Postscript.
*/
EPS("252150532D41646F6265"),
/**
* Adobe Acrobat.
*/
PDF("255044462D312E"),
/**
* Quicken.
*/
QDF("AC9EBD8F"),
/**
* Windows Password.
*/
PWL("E3828596"),
/**
* ZIP Archive.
*/
ZIP("504B0304"),
/**
* RAR Archive.
*/
RAR("52617221"),
/**
* Wave.
*/
WAV("57415645"),
/**
* AVI.
*/
AVI("41564920"),
/**
* Real Audio.
*/
RAM("2E7261FD"),
/**
* Real Media.
*/
RM("2E524D46"),
/**
* MPEG (mpg).
*/
MPG("000001BA"),
/**
* Quicktime.
*/
MOV("6D6F6F76"),
/**
* Windows Media.
*/
ASF("3026B2758E66CF11"),
GZ("1F8B08"),
/**
* MIDI.
*/
MID("4D546864");
private String value = "";
/**
* Constructor.
* @param value
*/
private FileType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
2.新建GetFileTypeUtil工具类,获取文件格式
代码如下(示例):
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @description 判断文件类型工具类
* @author 13192
*/
public class GetFileTypeUtil {
/**
* @description 第一步:获取文件输入流
* @param filePath
* @throws IOException
*/
private static String getFileContent(String filePath) throws IOException {
byte[] b = new byte[20];
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
/**
* int read() 从此输入流中读取一个数据字节。int read(byte[] b) 从此输入流中将最多 b.length
* 个字节的数据读入一个 byte 数组中。 int read(byte[] b, int off, int len)
*从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
* 之所以从输入流中读取20个字节数据,是因为不同格式的文件头魔数长度是不一样的,比如 EML("44656C69766572792D646174653A")和GIF("47494638")
* 为了提高识别精度所以获取的字节数相应地长一点
*/
inputStream.read(b, 0, 20);
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
}
return bytesToHexString(b);
}
/**
* @description 第二步:将文件头转换成16进制字符串
* @param
* @return 16进制字符串
*/
private static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
System.out.println("文件类型16进制字符串是"+stringBuilder.toString());
return stringBuilder.toString();
}
/**
* @description 第三步:根据十六进制字符串判断文件类型格式
* @param filePath 文件路径
* @return 文件类型
*/
public static FileType getType(String filePath) throws IOException {
String fileHead = getFileContent(filePath);
if (fileHead == null || fileHead.length() == 0) {
return null;
}
fileHead = fileHead.toUpperCase();
FileType[] fileTypes = FileType.values();
for (FileType type : fileTypes) {
// startsWith() 方法用于检测字符串是否以指定的前缀开始
if (fileHead.startsWith(type.getValue())) {
return type;
}
}
return null;
}
}
3.使用方法
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
/**
* @author : MasterWei
* @date : 2020-12-10 21:53
* @description :
* @params :
* @return :
**/
public class test {
public static void main(String[] args) throws Exception {
//故意把png文件的后缀改成txt,看是否能获取到真实文件格式
final String filePath = getFileType("C:\\Users\\13192\\Pictures\\123.png.txt");
String name=GetFileTypeUtil.getType(filePath).name();
System.out.println("文件格式是"+name);
}
总结
本文简单示例了Java如何获取真实文件格式的小demo,其中FileType枚举类可以在实际应用中添加更多对应的魔数,以增强识别读。
原文作者:majier
原文地址: https://blog.csdn.net/wxingna/article/details/110956405
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/wxingna/article/details/110956405
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章