Ubuntu下打开jpg图片提示Error interpreting JPEG image file (Not a JPEG file: starts with 0x89 0x50)错误

本文探讨了Java后台如何处理在Windows上正常显示而在Ubuntu下报错的JPEG图片问题,通过检查文件签名解决,并提及如何增强文件类型验证以防止恶意文件欺骗。实现代码展示了如何通过解析文件头判断文件类型。
摘要由CSDN通过智能技术生成

文章目录

问题

java后台接收一张jpg格式图片,发现其在windows下可以正常打开并显示图片内容,但在Ubuntu下打开却提示Error interpreting JPEG image file (Not a JPEG file: starts with 0x89 0x50)。如下图所示:
打开jpg图片错误截图
提示该文件不是JPEG图像文件,文件开头两个字节分别是0x89、0x50。

解决办法

通过维基百科List_of_file_signatures了解到,这两个字节开头的文件签名应该是png文件格式,将文件后缀名修改为png,再打开文件就可以正常显示。
png文件签名截图
为此在后台接口增加判断文件签名的逻辑,防止前端提交的后缀名并不是文件的真正格式(不仅限于图片)。

对于特意伪造文件头信息的恶意文件,下列逻辑无法起到甄别作用。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class filetools
{
	public final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();

	static
	{
		getAllFileType();
	}

	private static void getAllFileType()
	{
		FILE_TYPE_MAP.put("jpg(JFIF)", "^FFD8FFE000104A4649460001"); // jpg JFIF file format
		FILE_TYPE_MAP.put("jpg(Exif)", "^FFD8FFE1.{4}457869660000"); // jpg Exif file format
		FILE_TYPE_MAP.put("jpeg", "^FFD8FFEE"); // jpeg
		FILE_TYPE_MAP.put("png", "^89504E470D0A1A0A"); // PNG (png)
		FILE_TYPE_MAP.put("bmp", "^424D"); // Windows Bitmap (bmp)
		FILE_TYPE_MAP.put("mp4", "^000000206674797069736F6D"); // ISO Base Media file (MPEG-4)
	}

	public final static String getFileByFile(File file)
	{
		String filetyp = null;
		byte[] fileheader = new byte[15]; // 只读取前面15个字节,依据实际需要读取一定的字节判断即可
		try
		{
			InputStream is = new FileInputStream(file);
			is.read(fileheader);
			filetyp = getFileTypeByStream(fileheader);
			is.close();
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return filetyp;
	}

	public final static String getFileTypeByStream(byte[] b)
	{
		String filetypeHex = String.valueOf(getFileHexString(b));
		Iterator<Entry<String, String>> entryiterator = FILE_TYPE_MAP.entrySet().iterator();
		while (entryiterator.hasNext())
		{
			Entry<String, String> entry = entryiterator.next();
			String fileTypeHexValue = entry.getValue();
			Pattern p = Pattern.compile(fileTypeHexValue);
			Matcher m = p.matcher(filetypeHex.toUpperCase());

			if (m.find()) // 只判断是否匹配成功一个
			{
				if (0 == m.start()) // 判断是否开头匹配
					return entry.getKey();
			}
		}
		return "unknow type";
	}

	public final static String getFileHexString(byte[] b)
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (b == null || b.length <= 0)
		{
			return null;
		}
		for (int i = 0; i < b.length; i++)
		{
			int v = b[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2)
			{
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	public static void main(String[] args)
	{
		File f = new File("/home/alderaan/111.jpg");
		if (f.exists())
		{
			String filetype = getFileByFile(f);
			System.out.println(filetype);
		} else
		{
			System.out.println(f.getPath() + " not found!");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值