背景:
最近的项目需要一个功能:提供一个接口将图片上传至mongoDB,并返回一个url.图片是以文件形式传到接口,然后将其转化为二进制数组上传到mongoDB,在这里呢,我需要判断图片的格式,根据格式返回不同的url.
现在我的问题是JPEG这个格式识别不出来,虽然我看网上JPG和JPEG是同一个格式,但是经过实践,这两还是有区别的.
所以我去看了识别工具的源码,主要就是这么一段,mag的前几位跟contents(字节数组)前几位对比.
public static String getFileFormat(byte[] contents) {
for (int i = 0; i < FILE_MAGS.length; i++) {
byte[] mag = FILE_MAGS[i];
if (contents.length >= mag.length) {
if (Arrays.equals(Arrays.copyOf(contents, mag.length), mag)) {
return FILE_EXTS[i];
}
}
}
return null;
}
mag取自FILE_MAGS数组,来看下FILE_MAGS内容
private static final byte[][] FILE_MAGS = new byte[][] {
new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0}, //JPG
new byte[] {(byte)0x89, (byte)0x50, (byte)0x4E, (byte)0x47}, //PNG
new byte[] {(byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38} //GIF
};
很直观啦,现在我就要取找JPEG图片转成字节数组后前四个字节是什么.
byte[] fileContent = FileUtils.readFileToByteArray(new File("/home/jiahui/Desktop/sdf.jpg"));
for(int i =0 ;i<4;i++){
System.out.println(String.format("0x%2x",fileContent[i]));
}
System.out.println();
fileContent = FileUtils.readFileToByteArray(new File("/home/jiahui/Desktop/O1CN01TzIMM824HfuuzCcRX_!!3776527366.jpeg"));
for(int i =0 ;i<4;i++){
System.out.println(String.format("0x%2x",fileContent[i]));
}
运行之后结果如下,得到了JPEG格式前4位,加到FILE_MAGES数组中,成功识别是JPEG格式
完整工具类
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import java.io.*;
import java.util.Arrays;
public class FormatJudge {
/**
* File extensions.
*/
private static final String[] FILE_EXTS = {"JPG", "JPEG","PNG", "GIF"};
/**
* Magic bytes in a file with above extension.
*/
private static final byte[][] FILE_MAGS = new byte[][] {
new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0}, //JPG
new byte[] {(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xDB}, //JPEG
new byte[] {(byte)0x89, (byte)0x50, (byte)0x4E, (byte)0x47}, //PNG
new byte[] {(byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38} //GIF
};
/**
* Get file format from file name.
* @param fileName file name
* @return file format, null if unsupported.
*/
public static String getFileFormat(String fileName) {
int dp = fileName.lastIndexOf(".");
if (dp == -1) return null;
String ext = fileName.substring(dp + 1).toUpperCase();
if (ext.equals("JPEG")) ext = "JPG"; //JPEG is JPG
if (ArrayUtils.indexOf(FILE_EXTS, ext) == -1) return null;
return ext;
}
/**
* Get file format by contents.
* @param contents file contents
* @return file format, null if unsupported.
*/
public static String getFileFormat(byte[] contents) {
for (int i = 0; i < FILE_MAGS.length; i++) {
byte[] mag = FILE_MAGS[i];
if (contents.length >= mag.length) {
if (Arrays.equals(Arrays.copyOf(contents, mag.length), mag)) {
return FILE_EXTS[i];
}
}
}
return null;
}
}