java mimetype_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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值