Java 使用魔数判断文件类型

news/2024/11/29 18:21:06/文章来源:https://www.cnblogs.com/lyu6/p/18577325

引言
在日常的开发工作中,一般是使用文案后缀去判断文件类型,这种不是很严谨,那么这样可通过修改文件名的方式去修改文件类型,如果将一个危险文件修成成png或者txt上传到文件服务器,后果难以估量。那么可以使用文件头魔数的方式去判断文件类型,这是一种比较安全的方式。

魔数介绍(Magic Number)
文件头魔数是指文件格式中用来标识文件类型的一段特定字节序列。它通常位于文件的开头部分,能够帮助操作系统或应用程序识别文件的格式和类型。
特点

  • 唯一性:每种文件格式通常都有一个独特的魔数。
  • 固定位置:魔数通常位于文件的开头,便于快速检查。
  • 二进制格式:魔数通常以二进制形式存储。

文件类型魔数枚举

package com.demo.utils;/*** 文件类型魔数枚举* 使用场景:用于判断文件类型,获取文件类型** @author lyu* @description:* @create 2024-11-29 15:43*/
public enum MagicNumnerFileTypeEnum {/*** JPG*/JPG("ffd8ff", "jpg"),/*** PNG*/PNG("89504e47", "png"),/*** GIF*/GIF_87("4749463837", "gif"),/*** GIF*/GIF_89("4749463839", "gif"),/*** TIF*/TIF("49492a00227105008037", "tif"),/*** Windows bitmap*/BMP_16("424d228c010000000000", "bmp"),/*** Windows bitmap*/BMP_24("424d8240090000000000", "bmp"),/*** Windows bitmap*/BMP_256("424d8e1b030000000000", "bmp"),/*** CAD*/DWG("41433130313500000000", "dwg"),/*** Rich Text Format*/RTF("7b5c727466315c616e73", "rtf"),/*** Adobe photoshop*/PSD("38425053000100000000", "psd"),/*** eml*/EML("46726f6d3a203d3f6762", "eml"),/*** Microsoft Access*/MDB("5374616E64617264204A", "mdb"),/*** Postscript*/PS("252150532D41646F6265", "ps"),/*** Adobe Acrobat*/PDF("255044462d312e", "pdf"),/*** rmvb*/RMVB("2e524d46000000120001", "rmvb"),/*** flv*/FLV("464c5601050000000900", "flv"),/*** MP4*/MP4("00000020667479706", "mp4"),/*** MP4*/MP4_ALT("00000018667479706d70", "mp4"),/*** MP3*/MP3("49443303000000002176", "mp3"),/*** mpg*/MPG("000001ba210001000180", "mpg"),/*** wmv*/WMV("3026b2758e66cf11a6d9", "wmv"),/*** wav*/WAV("52494646e27807005741", "wav"),/*** AVI*/AVI("52494646d07d60074156", "avi"),/*** MID*/MID("4d546864000000060001", "mid"),/*** ARAR Archive*/RAR("526172211a0700cf9073", "rar"),/*** INI*/INI("235468697320636f6e66", "ini"),/*** JAR*/JAR("504B03040a0000000000", "jar"),/*** JAR*/JAR_ALT("504B0304140008000800", "jar"),/*** Microsoft Word/Excel*/XLS("d0cf11e0a1b11ae10", "xls"),/*** ZIP Archive*/ZIP("504B0304", "zip"),/*** windows exe*/EXE("4d5a9000030000000400", "exe"),/*** JSP*/JSP("3c25402070616765206c", "jsp"),/*** MF*/MF("4d616e69666573742d56", "mf"),/*** java*/JAVA("7061636b616765207765", "java"),/*** windows script*/BAT("406563686f206f66660d", "bat"),/*** GZ*/GZ("1f8b0800000000000000", "gz"),/*** java bytecode*/CLASS("cafebabe0000002e0041", "class"),/*** CHM*/CHM("49545346030000006000", "chm"),/*** mxp*/MXP("04000000010000001300", "mxp"),/*** torrent*/TORRENT("6431303a637265617465", "torrent"),/*** mov*/MOV("6D6F6F76", "mov"),/*** Word Perfect*/WPD("FF575043", "wpd"),/*** Outlook Express*/DBX("CFAD12FEC5FD746F", "dbx"),/*** Outlook*/PST("2142444E", "pst"),/****/QDF("AC9EBD8F", "qdf"),/*** windows password*/PWL("E3828596", "pwl"),/*** Real Audio*/RAM("2E7261FD", "ram");private final String key;private final String value;MagicNumnerFileTypeEnum(String key, String value) {this.key = key;this.value = value;}public String getValue() {return value;}public String getKey() {return key;}}

文件类型判断工具类

package com.demo.utils;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;/*** @author lyu* @version: 1.0* @create 2024-11-29 16:24*/
public class FileTypeUtils {private static final String EMPTY = "";private static final String DOT = ".";private static final int OFFSET = 28;private static final int INDEX_NOT_FOUND = -1;/*** 类Unix路径分隔符*/public static final char UNIX_SEPARATOR = '/';;/*** Windows路径分隔符*/public static final char WINDOWS_SEPARATOR = '\\';private FileTypeUtils() {throw new UnsupportedOperationException("Disabled use refection to create instance!!");}/*** 获取文件头** @param inputStream 输入流* @return 16 进制的文件投信息* @throws IOException io异常*/private static String getFileHeader(InputStream inputStream) throws IOException {byte[] b = new byte[28];inputStream.read(b, 0, 28);return bytes2hex(b);}/*** 将字节数组转换成16进制字符串** @param src 文件字节数组* @return 16进制字符串*/private static String bytes2hex(byte[] src) {StringBuilder stringBuilder = new StringBuilder();if (src == null || src.length == 0) {return null;}for (byte b : src) {int v = b & 0xFF;String hv = Integer.toHexString(v);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString().toUpperCase();}private static byte[] getFileTypeByte(byte[] bytes) {byte[] fileTypeByte = new byte[OFFSET];int offset = Math.min(bytes.length, OFFSET);System.arraycopy(bytes, 0, fileTypeByte, 0, offset);return fileTypeByte;}public static String getFileType(byte[] bytes, String filename) {byte[] fileTypeByte = getFileTypeByte(bytes);String fileHeader = bytes2hex(fileTypeByte);String typeName = getType(fileHeader);if (null == typeName) {return extName(filename);}if ("zip".equalsIgnoreCase(typeName)) {// zip可能为docx、xlsx、pptx、jar、war等格式,扩展名辅助判断final String extName = extName(typeName);if ("docx".equalsIgnoreCase(extName)) {typeName = "docx";} else if ("xlsx".equalsIgnoreCase(extName)) {typeName = "xlsx";} else if ("pptx".equalsIgnoreCase(extName)) {typeName = "pptx";} else if ("jar".equalsIgnoreCase(extName)) {typeName = "jar";} else if ("war".equalsIgnoreCase(extName)) {typeName = "war";}}return typeName;}private static String extName(String filename) {if (filename == null) {return null;}int index = filename.lastIndexOf(DOT);if (index == -1) {return EMPTY;} else {String ext = filename.substring(index + 1);// 扩展名中不能包含路径相关的符号return containsAny(ext, UNIX_SEPARATOR, WINDOWS_SEPARATOR) ? EMPTY : ext;}}public static boolean containsAny(CharSequence str, char... testChars) {if (!isEmpty(str)) {int len = str.length();for (int i = 0; i < len; i++) {if (contains(testChars, str.charAt(i)) > INDEX_NOT_FOUND) {return true;}}}return false;}private static int contains(char[] array, char value) {if (null != array) {for (int i = 0; i < array.length; i++) {if (value == array[i]) {return i;}}}return INDEX_NOT_FOUND;}private static boolean isEmpty(CharSequence str) {return str == null || str.length() == 0;}private static String getType(String fileHeader) {for (MagicNumnerFileTypeEnum fileTypeEnum : MagicNumnerFileTypeEnum.values()) {if (fileHeader.startsWith(fileTypeEnum.getValue())) {return fileTypeEnum.getKey();}}return null;}/*** 判断指定输入流是否是指定文件格式** @param inputStream  文件流* @param fileTypeEnum 文件格式枚举* @return 结果* @throws IOException io异常*/public static boolean isFileType(InputStream inputStream, MagicNumnerFileTypeEnum fileTypeEnum) throws IOException {if (null == inputStream) {return false;}String fileHeader = getFileHeader(inputStream);return fileHeader.startsWith(fileTypeEnum.getValue());}public static void main(String[] args) throws IOException {String str = "E:\\a.docx";FileInputStream inputStream = new FileInputStream(str);byte[] b = new byte[inputStream.available()];inputStream.read(b, 0, inputStream.available());System.out.println(getFileType(b, str));}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/843561.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录---前端如何优雅通知用户刷新页面?

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣前言 老板:新的需求不是上线了嘛,怎么用户看到的还是老的页面呀 窝囊废:让用户刷新一下页面,或者清一下缓存 老板:那我得告诉用户,刷新一下页面,或者清一下缓存,才能看到新的页面呀,感觉用户体验不好啊,不能直接…

一文多发小工具

一个一文多发的发布小工具 一个一文多发的发布小工具,作为练手的项目。 概述: 如果有将文章分享到多个平台的需求,可以借助程序来简化这一过程,节省时间并提高效率。 实现思路: 大多数平台支持markdown格式的文本内容,将.md文件作为入口文件读取,发布到各个平台;由于ma…

为 TVM 添加对 Paddle 量化模型的支持

1 简介 随着深度学习应用的广泛使用,量化模型作为一种有效的模型压缩技术,能够在保持模型精度的同时减少模型的计算和存储开销。本文将介绍如何在 TVM 上为 Paddle 深度学习框架中的量化模型提供解析支持。 2 量化方法 目前主流的的量化方法主要分为 QOperator 和 QDQ(Quanti…

tp6 url 规则

http://tp.cc/index.php/index/test return view( index, [info => $info, sj=>$sj] );

拥抱 OpenTelemetry:阿里云 Java Agent 演进实践

我们用了接近一年的时间完成了基于 OTel Java Agent 的升级重构,并于今年 5 月份发布了 4.x 探针的第一个版本 4.1.0,经过接近半年时间的验证、回归、优化,目前最新的稳定版本 4.1.12[11]已经正式发布,欢迎大家了解使用。作者:陈承 背景 在 2018 年的 2 月,ARMS Java Age…

BIM技术:数字孪生城区建设的加速器

在智慧城市建设的浪潮中,BIM(建筑信息模型)技术以其独特的优势,成为推动数字孪生城区建设的重要技术力量。本文将探讨BIM技术如何成为数字孪生城区建设的加速器,以及其在建设过程中的关键作用。BIM技术与数字孪生城区的融合数字孪生城区是指在数字空间构建一个与实体城市相…

ADF - [01] 概述

题记部分 001 || 简介Azure Data Factory (ADF) 是微软 Azure 云平台提供的一种数据集成服务,它允许用户创建、安排和管理数据管道,以实现从不同来源抽取数据、转换数据并加载到目标存储的过程。这个过程通常被称为 ETL(Extract, Transform, Load)。002 || 适用场景 【1】…

使用Powershell运行脚本报错的处理方法

最近在一台办公电脑上运行powershell脚本时报错如下: 系统上禁止运行脚本。有关详细信息,请参阅 https :/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 + .\CreateFolders.ps1 + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : S…

20222408 2021-2022-2 《网络与系统攻防技术》实验七实验报告

1.实验内容 1.1实验内容简述 (1)应用SET工具建立冒名网站。 (2)利用ettercap完成DNS欺骗攻击。 (3)结合应用两种技术,使被攻击者会通过域名访问到冒名网站。 (4)结合攻击过程,提出具体防范方法。 1.2学习内容简述 (1)学习SET工具和ettercap工具的使用。 (2)理解A…

Vulnhub sick0s1.1

0x01:端口扫描 主机发现 nmap -sn 192.168.231.0/24全端口扫描 nmap --min-rate 10000 -p- 192.168.231.14122ssh,3128squid-http,但8080http是关闭的Squid 是一个高性能的开源代理服务器软件,它支持多种协议,包括 HTTP、HTTPS、FTP 等。它通常用于以下几种用途: 1、Web代…

Gemini

Gemini: 大规模DNN芯片阵列加速器的布局和架构 摘要 chiplet概要目标Chiplet(芯片阵列)技术允许在单一加速器上集成不断增加的晶体管的数量,在前摩尔定律时代获得了更高的效果,体现了在快速AI迭代进步中需要的大量算力。 但是,这样也引进了更高昂的大包开销,以及大量的d2…

hhdb数据库介绍(10-19)

监控 智能物理拓扑 物理拓扑图主要以服务器为视角展示集群组件与服务器的所属关系,同时可查看服务器资源的使用情况以及各集群组件服务运行状态。使用前需保证为集群服务器配置了可用的SSH连接信息,否则只能查看当前服务器与集群组件的所属关系,无法查看服务器与组件程序的状…