Kotlin实现HTML转PDF字节数组时提示无效Base64字符25如何解决
问题描述
基于Kotlin实现从HTML内容生成PDF的功能,要求生成的PDF不保存为本地文件,最终输出ByteArray类型用于上传至服务端。
初始实现采用Jsoup清洗HTML内容,再通过ITextRenderer生成PDF,核心代码如下:
val sanitizedHTML = Jsoup.clean(html, whitelist) val textRenderer = ITextRenderer() val outputStream = ByteArrayOutputStream() textRenderer.setDocumentFromString(sanitizedHTML) textRenderer.layout() textRenderer.createPDF(outputStream) textRenderer.finishPDF() return Base64.getDecoder().decode(outputStream.toByteArray())
代码运行时持续抛出invalid Base64 character 25错误。
问题根因
最后一行的Base64解码逻辑完全多余:ITextRenderer.createPDF()写入ByteArrayOutputStream的内容本身就是原生PDF格式的二进制字节流,并非Base64编码后的字符串。将原生二进制字节直接传入Base64解码器时,解码器会把字节值当做Base64字符做合法性校验,值为25的字节属于ASCII控制字符,不在Base64合法字符范围内,因此抛出参数错误。
修正方案
- 删除多余的Base64解码步骤,直接返回输出流中的字节数组即可。
- 补充两个兼容性优化点,避免后续出现解析、布局异常:
- Jsoup
clean()方法默认输出的是HTML片段,需要补全XHTML文档声明与命名空间,否则ITextRenderer(基于Flying Saucer实现)可能出现样式解析失败、布局错乱问题。 - 用Kotlin内置的
use块自动关闭流,避免资源泄漏。
- Jsoup
修正后的可运行代码如下:
// 清洗HTML后补全标准XHTML文档结构,适配ITextRenderer解析要求 val sanitizedHTML = Jsoup.clean(html, whitelist) val fullXhtml = """ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta charset="UTF-8"></head> <body> $sanitizedHTML </body> </html> """.trimIndent() val textRenderer = ITextRenderer() // use块会在代码块执行完成后自动关闭流,无需手动处理 return ByteArrayOutputStream().use { outputStream -> textRenderer.setDocumentFromString(fullXhtml) textRenderer.layout() textRenderer.createPDF(outputStream) textRenderer.finishPDF() // 直接返回PDF原生字节数组,无需Base64编解码 outputStream.toByteArray() }
如果服务端接口要求传Base64编码后的PDF字符串,才需要对最终的字节数组做
Base64.getEncoder().encodeToString()处理,而非解码操作。
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

