您的位置:首页 > 编程语言 > Java开发

Java 读取图片的mimeType的方法

2018-01-23 13:53 381 查看

一、问题描述

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java mimeType