PDFBox从1.8.8升级到2.0.26后打印PDF出现U+0000编码异常求助
PDFBox升级后打印PDF出现U+0000编码异常问题
将PDFBox从1.8.8版本升级到2.0.26后,部分场景下打印PDF会抛出异常,已尝试更换fontbox/pdfbox版本但未解决。1.8.8版本无此问题,推测是U+0000空字符导致的编码兼容问题。
异常堆栈
Exception type: class javax.ejb.EJBException Exception message: javax.servlet.ServletException: See nested exception; nested exception is: java.lang.IllegalArgumentException: U+0000 is not available in this font's encoding: WinAnsiEncoding User agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Stack trace: javax.servlet.ServletException: See nested exception; nested exception is: java.lang.IllegalArgumentException: U+0000 is not available in this font's encoding: WinAnsiEncoding at javax.faces.webapp.FacesServlet.service(FacesServlet.java:606) at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1290) at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:778) at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:152) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:94) at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:111) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:1021) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1143) at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:82) at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:956) at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$2.run(DynamicVirtualHost.java:280) at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:967) at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.wrapHandlerAndExecute(HttpDispatcherLink.java:359) at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink.ready(HttpDispatcherLink.java:318) at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:471) at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.handleNewRequest(HttpInboundLink.java:405) at com.ibm.ws.http.channel.internal.inbound.HttpInboundLink.processRequest(HttpInboundLink.java:285) at com.ibm.ws.http.channel.internal.inbound.HttpICLReadCallback.complete(HttpICLReadCallback.java:66) at com.ibm.ws.tcpchannel.internal.WorkQueueManager.requestComplete(WorkQueueManager.java:504) at com.ibm.ws.tcpchannel.internal.WorkQueueManager.attemptIO(WorkQueueManager.java:574) at com.ibm.ws.tcpchannel.internal.WorkQueueManager.workerRun(WorkQueueManager.java:929) at com.ibm.ws.tcpchannel.internal.WorkQueueManager$Worker.run(WorkQueueManager.java:1018) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
相关代码
页脚文本添加代码
private static void addFooterText(PDPageContentStream contentStream, PdfProperties.AwFuer gesellschaftVon, PdfProperties.AwFuer gesellschaftFuer, PdfDocType docType) throws IOException { PDFont font = PDType1Font.HELVETICA; contentStream.beginText(); contentStream.setFont(font, 6); contentStream.newLineAtOffset(225, 24); String docTypeKsu = getKsuDocType(docType); if (!TextConstants.AUDI_BESTELLUNG.equals(docTypeKsu)) { String gkzFuer = gesellschaftFuer.getGesellschaftFuer(); String gkzVon = gesellschaftVon.getGesellschaftFuer(); String ksuString = KsuTextFrontEnd.getKsuText(docTypeKsu, gkzVon, gkzFuer); // CR819 contentStream.showText(ksuString); // CR819 } } private static void addFooterTextFinal(PDPageContentStream contentStream, PdfProperties.AwFuer gesellschaftVon, PdfProperties.AwFuer gesellschaftFuer, PdfDocType docType) throws IOException { PDFont font = PDType1Font.HELVETICA; contentStream.beginText(); contentStream.setFont(font, 6); contentStream.newLineAtOffset(225, 24); String docTypeKsu = getKsuDocType(docType); String gkzFuer = gesellschaftFuer.getGesellschaftFuer(); String gkzVon = gesellschaftVon.getGesellschaftFuer(); String ksuString = KsuTextFrontEnd.getKsuText(docTypeKsu, gkzVon, gkzFuer); contentStream.showText(ksuString); }
PDF创建代码
public void create(Map hashmap, OutputStream out, String FormularName) throws PdfException { PDDocument pdf = null; try { pdf = PDDocument.load(new File(FormularName)); PDDocumentCatalog docCatalog = pdf.getDocumentCatalog(); PDAcroForm acroForm = docCatalog.getAcroForm(); List<?> fields = acroForm.getFields(); Iterator<?> fieldsIter = fields.iterator(); while (fieldsIter.hasNext()) { PDField field = (PDField) fieldsIter.next(); String value = field.getPartialName().toString(); if (hashmap.containsKey(value)) { field.setValue((String) hashmap.get(value)); } else { continue; } } try { pdf.save(out); } catch (IOException e) { LOGGER.error(e); throw new PdfException(e.getMessage()); } } catch (IOException e2) { LOGGER.error(e2); throw new PdfException(e2.getMessage()); } finally { if (pdf != null) { try { pdf.close(); } catch (IOException e) { LOGGER.error(e); } } } }
问题分析与解决方法
原因
PDFBox 2.x版本对字符编码的校验比1.8.x更严格,U+0000(空字符)不属于WinAnsiEncoding的支持范围,当调用showText传入包含该字符的字符串时会直接抛出异常;而1.8.x版本可能自动忽略了这类非法字符,因此无报错。
解决方法
- 过滤非法字符:在调用
showText前,对字符串中的U+0000进行替换或移除,示例:
ksuString = ksuString.replace("\u0000", ""); // 或者移除所有控制字符(可选) ksuString = ksuString.replaceAll("\\p{Cntrl}", "");
- 检查数据源:排查
gesellschaftFuer.getGesellschaftFuer()、gesellschaftVon.getGesellschaftFuer()以及KsuTextFrontEnd.getKsuText的返回值,确保源头数据不包含空字符。 - 字体编码适配:如果业务需要保留特殊字符,可以尝试使用支持Unicode编码的字体(如
PDType0Font加载TrueType字体),但此方法复杂度较高,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Vieckov
相关产品推荐
相关产品推荐

