当前位置:   article > 正文

如何判断一个文件的类型_判断文件类型

判断文件类型

在文章应用安全系列之二十四:文件上传_jimmyleeee的博客-CSDN博客描述了上传文件时需要判断文件的几个方面,其中一个就是文件的类型,当然,如果要根据文件的后缀判断,也能满足大部分需求,如果确实需要判断文件的类型,或者某些时刻文件没有扩展名时,就会遇到麻烦。

文件类型检测分为两种:

  • 文件名检测 - 简单地根据文件后缀名判断文件类型。
  • 魔术字检测 - 有些文件格式会将文件最开始的几个字节设置会特定的模式,通过这些特殊的字节模式,可以判断文件类型。

Java提供了集中方法来判断一个文件的类型,其中比较常用的方法是:Files.probeContentType,但是,它有一个缺点就是,当文件没有扩展名时,返回的结果是null,下面是一个使用这个方法的代码:

  1. public class TestApp {
  2. public static String identifyFileType(final String fileName) throws IOException
  3. {
  4. final File file = new File(fileName);
  5. return Files.probeContentType(file.toPath());
  6. }
  7. public static void main(String[] args) {
  8. String fileNames[] = {"F:\\filetype\\1.pdf",
  9. "F:\\filetype\\2.zip",
  10. "F:\\filetype\\3.docx",
  11. "F:\\filetype\\4.xls",
  12. "F:\\filetype\\5.jpg",
  13. "F:\\filetype\\6.csv",
  14. "F:\\filetype\\7.txt",
  15. "F:\\filetype\\8.PNG",
  16. "F:\\filetype\\9.mp4",
  17. "F:\\filetype\\10.xml",
  18. "F:\\filetype\\11.xml",
  19. "F:\\filetype\\noextpng",
  20. "F:\\filetype\\csvnoext",
  21. "F:\\filetype\\mp4noext",
  22. "F:\\filetype\\pngwithtxt.txt",
  23. };
  24. // Test Files.probeContentType
  25. System.out.println("Test Files.probeContentType Begin");
  26. try {
  27. for (String fileName : fileNames) {
  28. System.out.println(identifyFileType(fileName));
  29. }
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. System.out.println("Test Files.probeContentType End");
  34. }
  35. }

打印结果如下:

  1. Test Files.probeContentType Begin
  2. application/pdf
  3. application/x-zip-compressed
  4. application/vnd.openxmlformats-officedocument.wordprocessingml.document
  5. application/vnd.ms-excel
  6. image/jpeg
  7. application/vnd.ms-excel
  8. text/plain
  9. image/png
  10. video/mp4
  11. text/xml
  12. application/json
  13. null
  14. null
  15. null
  16. text/plain
  17. Test Files.probeContentType End

可以看到,Files.probeContentType是根据扩展名来判断文件类型的,没有扩展名时,返回的是null,当把一个图片改成txt结尾,返回的类型和txt的类型一样。说明如果要根据Files.probeContentType准确判断一个文件的类型是不准确的。

Java还提供了其他几个方法获取文件的类型:

类与方法名说明
MimetypesFileTypeMap::getContentType
只有jpg和txt返回正常,其他全部返回application/octet-stream
URLConnection::getContentType
和Files.probeContentType类似。不同的是,它识别的XML文件的类型是application/xml,而Files.probeContentType识别的XML是text/xml.
URLConnection.guessContentTypeFromName
测试了除了pdf、zip、jpg、txt、png、xml返回的值正常,其它全部返回null

综上所述,目前Java提供的几种方法都不能很好地准确地判断文件的类型,不过,幸运的是Apache提供了Tika,下面是使用默认的Tika的功能的代码:

  1. public static String getFileTypeByDefaultTika(final String fileName)
  2. {
  3. Tika defaultTika = new Tika();
  4. String fileType;
  5. try
  6. {
  7. final File file = new File(fileName);
  8. fileType = defaultTika.detect(file);
  9. }
  10. catch (IOException ioEx)
  11. {
  12. fileType = "Unknown";
  13. }
  14. return fileType;
  15. }

使用本文开头的示例代码打印信息如下:

  1. Test DefaultTikaForFile Begin
  2. application/pdf
  3. application/zip
  4. application/vnd.openxmlformats-officedocument.wordprocessingml.document
  5. application/vnd.ms-excel
  6. image/jpeg
  7. text/csv
  8. text/plain
  9. image/png
  10. video/mp4
  11. application/xml
  12. application/json
  13. image/png
  14. text/plain
  15. video/quicktime
  16. image/png
  17. Test DefaultTikaForFile End

可以看到,所有的文件类型都识别出来了,没有扩展名的文件也是别出来,最为重要的是,我把图片改成txt后缀,它也是别出来这是一个png。

Tika还提供了其他实现,下面表格是将集中的实现结果的比较:

Tika实现方式示例代码说明
默认Tika defaultTika = new Tika();根据上述代码打印结果,完全符合预期,效果最好;
MIMETika mimeTika = new Tika(new MimeTypes());除了txt文件正常输出text/plain,其他全部是application/octet-stream;
TypeDetectorTika typeTika = new Tika(new TypeDetector());全部输出为application/octet-stream;

综上所述,如果需要比较准确地判断一个文件到底是什么类型,不管扩展名是什么,需要使用Tika的默认实现方式;如果只需要根据扩展名判断文件类型就够了,你可以使用Files.probeContentType和URLConnection::getContentType。

关于PHP也有几种获取文件类型的方法,总结如下表:

类与方法名说明
pathinfo($file, PATHINFO_EXTENSION)仅仅是根据文件的扩展名返回文件类型
$_FILES[‘uploadfile’][‘type’]仅仅是根据文件的扩展名返回文件类型
finfo_file(
    resource $finfo,
    string $file_name = null,
    int $options = FILEINFO_NONE,
    resource $context = null
): string
本函数用来获取一个文件的信息。该方法即便是原文件被改过后缀,已然可以读到原文件类型。

总之,在处理文件上传时需要谨记需要做好输入验证,不管是文件名、大小、类型,还是内容等,只有做好了防范,才能预防由文件上传带来的攻击。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/831539
推荐阅读
相关标签
  

闽ICP备14008679号