Java 读取图片的mimeType


声明:本文转载自https://my.oschina.net/ososchina/blog/1610685,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

一、问题描述

在项目开发的时候,我们经常会遇到一类文件上传的问题,就是获取图片是哪种格式。很多情况下,很多人都是用后缀名去判断,如下所示。

if(filename.endsWith(".png") || filename.endsWith(".jpg")) {    //保存图片  }else{    throw new IOException("Error file format !");  }

但是这种方式相当不可靠,我们可以尝试将zip文件、rmvb文件、css、js修改后缀名位jpg或者png上传,也可以上传到服务器,这就造成我们服务器上出现了脏数据。此外,对于有些图片文件,修改成错误的扩展名,有些浏览器可能无法显示出此图片。

 

二、解决方案

在计算机系统中,媒体类型的文件都有【标识符】,zip、图片本身属于媒体文件,因此我们可以通过编解码的方式判断图片是否合法。

1、判断标示方法

private static boolean isBMP(byte[] buf){ 		byte[] markBuf = "BM".getBytes();  //BMP图片文件的前两个字节 		return compare(buf, markBuf); 	} 	 	private static boolean isICON(byte[] buf) { 		byte[] markBuf = {0, 0, 1, 0, 1, 0, 32, 32}; 		return compare(buf, markBuf); 	} 	private static boolean isWEBP(byte[] buf) { 		byte[] markBuf = "RIFF".getBytes(); //WebP图片识别符 		return compare(buf, markBuf); 	}  	private static boolean isGIF(byte[] buf) { 		 		byte[] markBuf = "GIF89a".getBytes(); //GIF识别符 		if(compare(buf, markBuf)) 		{ 			return true; 		} 		markBuf = "GIF87a".getBytes(); //GIF识别符 		if(compare(buf, markBuf)) 		{ 			return true; 		} 		return false; 	}  	 	private static boolean isPNG(byte[] buf) { 		 		byte[] markBuf = {(byte) 0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A}; //PNG识别符 		 // new String(buf).indexOf("PNG")>0 //也可以使用这种方式 		return compare(buf, markBuf); 	}  	private static boolean isJPEGHeader(byte[] buf) { 		byte[] markBuf = {(byte) 0xff, (byte) 0xd8}; //JPEG开始符 		 		return compare(buf, markBuf); 	} 	 	private static boolean isJPEGFooter(byte[] buf)//JPEG结束符 	{ 		byte[] markBuf = {(byte) 0xff, (byte) 0xd9};  		return compare(buf, markBuf); 	}

2、核心方法

/** 	 * 获取文件的mimeType 	 * @param filename 	 * @return 	 */ 	private static String getMimeType(String filename){ 		try { 			String mimeType = readType(filename); 			return String.format("image/%s", mimeType); 		} catch (IOException e) { 			e.printStackTrace(); 		} 		return null; 	}  	/** 	 * 读取文件类型 	 * @param filename 	 * @return 	 * @throws IOException 	 */ 	private static String readType(String filename) throws IOException { 		 		FileInputStream fis = null; 		try { 			File f = new File(filename); 			if(!f.exists() || f.isDirectory() || f.length()<8) { 				throw new IOException("the file ["+f.getAbsolutePath()+"] is not image !"); 			} 			 			fis= new FileInputStream(f); 			byte[] bufHeaders = readInputStreamAt(fis,0,8); 			if(isJPEGHeader(bufHeaders)) 			{	 				long skiplength = f.length()-2-8; //第一次读取时已经读了8个byte,因此需要减掉 				byte[] bufFooters = readInputStreamAt(fis, skiplength, 2); 				if(isJPEGFooter(bufFooters)) 				{ 					return "jpeg"; 				} 			} 			if(isPNG(bufHeaders)) 			{ 				return "png"; 			} 			if(isGIF(bufHeaders)){ 				 				return "gif"; 			} 			if(isWEBP(bufHeaders)) 			{ 				return "webp"; 			} 			if(isBMP(bufHeaders)) 			{ 				return "bmp"; 			} 			if(isICON(bufHeaders)) 			{ 				return "ico"; 			} 			throw new IOException("the image's format is unkown!"); 			 		} catch (FileNotFoundException e) { 			throw e; 		}finally{ 			try { 				if(fis!=null) fis.close(); 			} catch (Exception e) { 			} 		} 		 	}  	 	/** 	 * 标示一致性比较 	 * @param buf  待检测标示 	 * @param markBuf 标识符字节数组 	 * @return 返回false标示标示不匹配 	 */ 	private static boolean compare(byte[] buf, byte[] markBuf) { 		for (int i = 0; i < markBuf.length; i++) { 			byte b = markBuf[i]; 			byte a = buf[i]; 			 			if(a!=b){ 				return false; 			} 		} 		return true; 	} 	/** 	 *  	 * @param fis 输入流对象 	 * @param skiplength 跳过位置长度 	 * @param length 要读取的长度 	 * @return 字节数组 	 * @throws IOException 	 */ 	private static byte[] readInputStreamAt(FileInputStream fis, long skiplength, int length) throws IOException 	{ 		byte[] buf = new byte[length]; 		fis.skip(skiplength);  // 		int read = fis.read(buf,0,length); 		return buf; 	} 	

3、测试代码

正常测试

public class ImageType {  	 	public static void main(String[] args) { 		 			String filename = "oschina.jpg"; 			String type = getMimeType(filename); 			System.out.println(type); 	} }

输出

image/jpeg

修改扩展名测试

①修改oschina.jpeg为oschina.png

②复制oschina.png删除扩展名

public class ImageType {  	 	public static void main(String[] args) { 		 			String filename = "oschina.png"; 			String type = getMimeType(filename); 			System.out.println(type); 		 			filename = "oschina"; 			type = getMimeType(filename); 			System.out.println(type);              	} }

输出

image/jpeg image/jpeg

 

本文发表于2018年01月22日 12:32
(c)注:本文转载自https://my.oschina.net/ososchina/blog/1610685,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1686 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1