admin 管理员组

文章数量: 887021


2024年1月10日发(作者:网站网页设计的意义)

【黑马程序员】Java如何判断文件的真实类型

在我们实现一些需求的时候,有时候需要让用户上传文件,例如做论坛、社交类的应用和服务。这时候可能就会出现一个需求:上传固定类型、固定大小的文件,也就是说,只允许用户上传图片或者文本、压缩包等。其他的格式禁止上传,以防止用户恶意操作。文件的大小非常容易判断,主要是文件类型如何确定。

有一种方式是按照扩展名去判断,例如图片就是.jpg、.png等,但是这种方式不准确,因为如果真是恶意上传,exe文件也可以修改为上传成功。所以,必须要用一种方式获取文件的真实类型。即使文件后缀名修改了,也能找出来它的原形。

这个地方我们需要先了解一些基本知识,就是所有的文件的开头都有一段头信息,用来承担一定的任务,而每个不同类型的文件的头信息都是不同的,所以我们可以按照这种方式来进行判断。

首先,我们需要获取到文件头里这几个字节的数据,很简单,使用输入流来读取即可。代码如下:

01 public static String getFileHeader(String filePath) {

02 FileInputStream is = null;

03 String value = null;

04 try {

05 is = new FileInputStream(filePath);

06 byte[] b = new byte[4];

07 (b, 0, );

08 value = bytesToHexString(b);

09 } catch (Exception e) {

10 } finally {

11 if (null != is) {

12 try {

13 ();

14 } catch (IOException e) {

15 }

16 }

17 }

18 return value;

黑马程序员济南中心 编著

19 }

这个地方很容易理解,就是把文件的前4个byte取出来了,但是取出来的数据我们需要转换为16进制的字符串来表示,才能判断出来究竟是什么内容。接下来,我们就把数据转换一下。Integer里有一个API可以直接输出16进制的字符串,所以我们可以先把byte转换为integer来表示。由于byte是一个字节,而integer是4个字节,所以不足的部分用0填充,即用byte与0xFF做一次与运算,完成byte到integer的转换,然后把16进制的数据输出,字符串转换为大写以便后面使用。

01 private static String bytesToHexString(byte[] src) {

02 StringBuilder builder = new StringBuilder();

03 if (src == null || <= 0) {

04 return null;

05 }

06 String hv;

07 for (int i = 0; i < ; i++) {

08

// 以十六进制(基数 16)无符号整数形式返回一个整数参数的字09

符串表示形式,并转换为大写

10 hv = tring(src[i] & 0xFF).toUpperCase();

11 if (() < 2) {

12 (0);

13 }

14 (hv);

15 }

16 return ng();

}

得到了头信息里的数据之后,我们拿到的其实是一堆看上去像乱码的字符串,并不能黑马程序员济南中心 编著

判断出来究竟是什么类型的文件,所以我们需要搜集常见的文件类型的头信息都是什么,然后用映射关系表来查找。我这里准备了一些常用的文件的头信息,已经封装到了一个map里,可以参考。

01 public static final HashMap mFileTypes = new HashMap

02 String>();

03 static {

04 // images

05 ("FFD8FF", "jpg");

06 ("89504E47", "png");

07 ("47494638", "gif");

08 ("49492A00", "tif");

09 ("424D", "bmp");

10 //

11 ("41433130", "dwg"); // CAD

12 ("38425053", "psd");

13

("7B5C727466", "rtf"); // 日记本

14 ("3C3F786D6C", "xml");

15 ("68746D6C3E", "html");

16

("44656C69766572792D646174653A", "eml"); // 邮件

17 ("D0CF11E0", "doc");

18

("D0CF11E0", "xls");// excel2003版本文件

19 ("5374616E64617264204A", "mdb");

20 ("252150532D41646F6265", "ps");

21 ("255044462D312E", "pdf");

22 ("504B0304", "docx");

23

("504B0304", "xlsx");// excel2007以上版本文件

24 ("52617221", "rar");

25 ("57415645", "wav");

26 ("41564920", "avi");

27 ("2E524D46", "rm");

28 ("000001BA", "mpg");

29 ("000001B3", "mpg");

30 ("6D6F6F76", "mov");

31 ("3026B2758E66CF11", "asf");

32 ("4D546864", "mid");

33 ("1F8B08", "gz");

}

黑马程序员济南中心 编著

这些都是一些固定的数据,我们现在有了map的key(其实就是上面我们最终获取到的字符串),直接去map里查找value就是文件的实际类型了。我们把一个png文件修改为试一下。打印结果是OK的。

这样,我们就可以把上面的代码整理封装为一个工具类来使用了,以后再处理文件上传的时候,就可以把一些恶意的操作屏蔽掉了。整体代码附到附件里自取吧。

黑马程序员济南中心 编著


本文标签: 文件 上传 需要 数据 字符串