我叫王小明,
我的身边发生了无法想象的灾难 !
FBI 警告
Are you really an adult?
友情链接
文件魔术值确定文件类型

魔术值

什么是魔术值?

  1. 魔术值就是文件的最开头的几个用于唯一区别其它文件类型的字节,
  2. 使用魔术值我们就可以很方便的区别不同的文件。

注意

  1. 不同文件类型的魔术值开头可能相同,所以区分的办法就是验证文件后缀和魔术值,
  2. 这样就保证文件是我们想要的文件类型啦。
  3. 文件校验很重要! 单纯的判断文件后缀 容易被坏人利用!

以下是我写的示例代码

凑合着用 理论上 没啥问题

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.web.multipart.MultipartFile;
  8. import com.alibaba.fastjson.JSONObject;
  9. public class CheckFileType {
  10. private static final Logger logger = LoggerFactory.getLogger(CheckFileType.class);
  11. public final static Map<String, String> FILE_TYPE = new HashMap<String, String>();
  12. /**
  13. * 魔术值开头相同的 要同时判断 后缀 与魔术对应 方可确定该文件
  14. */
  15. static {
  16. FILE_TYPE.put("mp3", "494433");
  17. FILE_TYPE.put("jpg", "FFD8FF");
  18. FILE_TYPE.put("png", "89504E47");
  19. FILE_TYPE.put("gif", "47494638");
  20. FILE_TYPE.put("xlsx", "504B0304"); // 与zip 相同开头
  21. FILE_TYPE.put("xls", "D0CF11E0");
  22. FILE_TYPE.put("zip", "504B0304");
  23. FILE_TYPE.put("doc", "D0CF11E0"); //与xls 相同开头
  24. FILE_TYPE.put("pdf", "255044462D312E"); //pdf文件
  25. FILE_TYPE.put("docx", "504B0304");//与zip 相同开头
  26. FILE_TYPE.put("rar", "52617221");
  27. //如果以上 文件类型不能满足你 ,问题不大 。 上传你需要 的文件 64行log打印的 魔术值 抬头自己加入map中即可
  28. }
  29. /**
  30. * 调用示例
  31. *
  32. * JSONObject obj = CheckFileType.getFileByFile(multipartFile);
  33. * if(!obj.getBoolean("state")) {
  34. * System.err.println("文件不合法");
  35. * }
  36. * 返回的json 中type 就是 该文件的类型
  37. *
  38. */
  39. public final static JSONObject getFileByFile(MultipartFile file) throws IOException {
  40. byte[] b = new byte[50];
  41. String fileName =file.getOriginalFilename();
  42. String fileType= fileName.substring(fileName.lastIndexOf(".") + 1);
  43. InputStream is =file.getInputStream();
  44. is.read(b);
  45. JSONObject obj = getFileType(b,fileType);
  46. is.close();
  47. return obj;
  48. }
  49. /**
  50. * 验证文件
  51. */
  52. public final static JSONObject getFileType(byte[] b,String fileType) {
  53. String fileTypeHex = String.valueOf(getFileHexString(b));
  54. logger.info("文件的魔术值 - {}",fileTypeHex);
  55. logger.info("未验证的文件后缀 - {}",fileType);
  56. JSONObject obj = new JSONObject();
  57. if(fileTypeHex.toUpperCase().startsWith(FILE_TYPE.get(fileType))) {
  58. obj.put("state", true);
  59. obj.put("type", fileType);
  60. obj.put("msg", "文件合法!");
  61. }else {
  62. obj.put("state", false);
  63. obj.put("msg", "未知文件!");
  64. }
  65. return obj;
  66. }
  67. /**
  68. * 获取文件的字节码
  69. */
  70. public final static String getFileHexString(byte[] b) {
  71. StringBuilder stringBuilder = new StringBuilder();
  72. if (b == null || b.length <= 0) {
  73. return "";
  74. }
  75. for (int i = 0; i < b.length; i++) {
  76. int v = b[i] & 0xFF;
  77. String hv = Integer.toHexString(v);
  78. if (hv.length() < 2) {
  79. stringBuilder.append(0);
  80. }
  81. stringBuilder.append(hv);
  82. }
  83. return stringBuilder.toString();
  84. }

}

赞赏
2018-08-02

发表评论