Java 读取图片的mimeType的方法

一、问题描述

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

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

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

(0)

相关推荐

  • Java 读取图片的mimeType的方法

    一.问题描述 在项目开发的时候,我们经常会遇到一类文件上传的问题,就是获取图片是哪种格式.很多情况下,很多人都是用后缀名去判断,如下所示. if(filename.endsWith(".png") || filename.endsWith(".jpg")) { //保存图片 }else{ throw new IOException("Error file format !"); } 但是这种方式相当不可靠,我们可以尝试将zip文件.rmvb文件.

  • Java读取图片EXIF信息的方法

    本文实例讲述了Java读取图片EXIF信息的方法.分享给大家供大家参考.具体分析如下: 首先介绍一下什么是EXIF,EXIF是Exchangeable Image File的缩写,这是一种专门为数码相机照片设定的格式.这种格式可以用来记录数字照片的属性信息,例如相机的品牌及型号.相片的拍摄时间.拍摄时所设置 的光圈大小.快门速度.ISO等等信息.除此之外它还能够记录拍摄数据,以及照片格式化方式,这样就可以输出到兼容EXIF格式的外设上,例如照片打印机 等. 目前最常见的支持EXIF信息的图片格式

  • java读取图片并转化为二进制字符串的实现方法

    本例子的目的在于测试往oracle数据库中插入blob字段 public static String getImgStr(String imgFile){ //将图片文件转化为字节数组字符串,并对其进行Base64编码处理 InputStream in = null; byte[] data = null; //读取图片字节数组 try { in = new FileInputStream(imgFile); data = new byte[in.available()]; in.read(da

  • Java读取Map的两种方法与对比

    前言 在java中遍历Map有不少的方法.这篇文章我们就来看一下Java读取Map的两种方法以及这两种方法的对比. 一. 遍历Map方法A Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); Object val = en

  • Java读取文件的简单实现方法

    本文实例讲述了Java读取文件的简单实现方法,非常实用.分享给大家供大家参考之用.具体方法如下: 这是一个简单的读取文件的代码,并试着读取一个log文件,再输出. 主要代码如下: import java.io.*; public class FileToString { public static String readFile(String fileName) { String output = ""; File file = new File(fileName); if(file.

  • Java读取String分行字符串的方法

    1.场景:String字符串中带有分行,需要提取每一行出来处理. 2.参考代码如下: public static void main(String[] args) throws IOException{ String s="1\r\n2\r\n3\r\n \r\nabd\r\n"; BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charse

  • Java读取TXT文件内容的方法

    Java读取txt文件内容.可以作如下理解: 首先获得一个文件句柄.File file = new File(); file即为文件句柄.两人之间连通电话网络了.接下来可以开始打电话了. 通过这条线路读取甲方的信息:new FileInputStream(file) 目前这个信息已经读进来内存当中了.接下来需要解读成乙方可以理解的东西 既然你使用了FileInputStream().那么对应的需要使用InputStreamReader()这个方法进行解读刚才装进来内存当中的数据 解读完成后要输出

  • Java读取Properties文件几种方法总结

    使用J2SE API读取Properties文件的六种方法 1.使用Java.util.Properties类的load()方法 示例: InputStream in = lnew BufferedInputStream(new FileInputStream(name)); Properties p = new Properties(); p.load(in); 2.使用java.util.ResourceBundle类的getBundle()方法 示例: ResourceBundle rb

  • Java读取properties文件连接数据库的方法示例

    之前我们在入门jdbc的时候,常用这种方法连接数据库: package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnectionManager { public static Connection getConnection() { Connection conn = null; try { Class.forName

  • Java读取其下所有文件夹与文件路径的方法

    Java读取其下所有文件夹与文件的路径,具体内容如下 如果在f:\aa文件夹中,有如下图的文件夹与文件: 那么,在Java中,则如此读取f:/aa下的所有文件路径: 1.首先由于用到了文件与容器类下的ArrayList,所以在开头要引入如下包: import java.io.*; import java.util.*; 2.方法如下,其中File dirFile除了盘符,比如f:,以外,能够接受一切合法的路径.由于盘符下含有一些系统文件,拒绝访问,因为读取盘符,可能会出现空指针异常. //这里是

随机推荐