从数据库读取用户签名生成PDF时触发java.io.IOException:字节数组不是可识别图像格式的解决方法求助
解决iText中
Image.getInstance(byte[])抛出"The byte array is not a recognized imageformat"异常的问题 这个问题我之前处理过,大概率是因为你从数据库获取的签名数据不是原始图片字节数组,而是Base64编码后的字符串——这是存储图片时的常见操作,但直接对这个字符串调用.getBytes()得到的是Base64文本的字节,而非图片本身的二进制数据,所以iText无法识别。下面给你分情况解决:
一、最常见的场景:签名是Base64编码字符串
1. 先确认数据格式
先打印e.getuserSigns()返回的内容,看是否符合Base64特征:
- 要么是纯Base64字符(由A-Z、a-z、0-9、+、/、=组成)
- 要么是带
data:image/png;base64,这类前缀的Data URI格式
2. 修正代码解码Base64
把Base64字符串解码为原始图片字节数组,再传给Image.getInstance():
// 替换原来的byte[] userSign = e.getuserSigns().getBytes(); String signBase64 = e.getuserSigns(); byte[] userSign; // 处理带Data URI前缀的情况 if (signBase64.startsWith("data:image/")) { // 分割前缀和实际Base64内容 signBase64 = signBase64.split(",")[1]; } // 解码Base64为图片字节 userSign = Base64.getDecoder().decode(signBase64);
二、其他可能的问题排查
1. 检查数据库存储的原始数据是否正确
如果解码后还是报错,那可能是存储的时候就出问题了:
- 把数据库中
userSigns字段的值导出来:如果是原始字节,直接保存为.png/.jpg文件;如果是Base64,解码后再保存。 - 尝试打开这个文件,如果打不开,说明存储时没有正确写入图片字节(比如存成了文件路径、或者读取图片时出错),需要回溯存储逻辑。
2. 修复代码中的循环冗余
你的代码里有两层嵌套循环:
for (int i = 0; i < user.size(); i++) { for (User e : user) { // ...处理逻辑 } }
这会导致每个用户的签名被重复处理user.size()次,完全没必要,直接去掉外层循环即可。
3. 注意绝对定位与表格的布局冲突
你用signpr.setAbsolutePosition(450, 80)设置了图片的绝对位置,但同时在操作PdfPTable,绝对定位的元素会直接覆盖在文档上,很可能和表格内容重叠,需要调整位置或者改用表格单元格来放置图片。
修正后的完整代码示例
import java.util.Base64; import com.itextpdf.text.BadElementException; import com.itextpdf.text.Element; import com.itextpdf.text.Image; import com.itextpdf.text.Phrase; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; // ...其他代码 PdfPTable userTable = new PdfPTable(1); if (!user.isEmpty()) { userTable.setWidthPercentage(100.0f); userTable.setWidths(new float[] { 6.5f }); // 只保留单层循环,避免重复处理 for (User e : user) { String signStr = e.getuserSigns(); if (signStr != null && !signStr.trim().isEmpty()) { try { byte[] userSign; // 处理Base64编码的签名 if (signStr.startsWith("data:image/")) { signStr = signStr.split(",")[1]; } userSign = Base64.getDecoder().decode(signStr); Image signpr = Image.getInstance(userSign); signpr.scaleToFit(100, 80); // 根据实际布局调整位置,避免和表格重叠 signpr.setAbsolutePosition(450, 80); doc.add(signpr); } catch (IOException | BadElementException ex) { // 单个签名加载失败时,不要中断整个PDF生成 ex.printStackTrace(); doc.add(new Phrase("【签名加载失败】")); } } // 处理用户名单元格 PdfPCell userName = new PdfPCell(new Phrase(e.getuserNames())); userName.setHorizontalAlignment(Element.ALIGN_CENTER); userName.setBorder(Rectangle.NO_BORDER); userTable.addCell(userName); } } doc.add(userTable);
额外注意事项
- 如果你的项目是Java 7及以下版本,
java.util.Base64不可用,需要使用Apache Commons Codec的org.apache.commons.codec.binary.Base64类,或者其他第三方Base64解码工具。 - 一定要添加异常捕获,避免因为单个用户的签名数据损坏导致整个PDF生成失败。
内容的提问来源于stack exchange,提问作者lakshman Kommula




