You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

从数据库读取用户签名生成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

火山引擎 最新活动