Spring Boot部署Ubuntu后PDF美元符号变¤的问题排查与解决
问题:PDF中的美元符号($)在Ubuntu服务器上变为通用货币符号(¤)
我有一个Spring Boot Web应用,通过接口生成PDF(以ByteArrayOutputStream形式)并以附件返回(转为ByteArrayInputStream)。本地MacOS环境运行时,PDF中的美元符号($)显示正常;但部署到AWS的Ubuntu服务器后,所有美元符号均变为通用货币符号(¤,Unicode U+00A4)。
Ubuntu版本信息:Linux ip-172-31-92-87 5.15.0-1023-aws #27-Ubuntu SMP Thu Oct 20 16:44:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
相关接口代码:
@PostMapping(value = "/invoice/upload", produces = { "application/pdf" }) public ResponseEntity<Object> handleFileUpload(@RequestParam("file") MultipartFile file, ... ) { // ...生成PDF的代码... String contentDispositionValue = "attachment; filename=\"" + simpleFilename + "\""; ByteArrayInputStream pdfInputStream = new ByteArrayInputStream(pdfOutputStream.toByteArray()); HttpHeaders headers = new HttpHeaders(); headers.add("content-disposition", contentDispositionValue); return ResponseEntity .ok() .headers(headers) .contentLength(pdfOutputStream.size()) .contentType(MediaType.parseMediaType("application/pdf")) .body(new InputStreamResource(pdfInputStream)); }
PDF生成依赖:
<groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version>
已尝试添加请求头Content-Type: application/pdf; charset=utf-8,但问题未解决。
问题原因
- 字体依赖环境差异:iText 2.1.7是非常老旧的版本,生成文本时若未显式指定字体,会依赖系统默认字体。MacOS默认字体(如Helvetica)完整包含$符号,但Ubuntu服务器的默认字体可能缺少该字符映射,或系统字符集配置导致编码转换错误,将$解析为¤。
- HTTP头charset无效:PDF是二进制格式,其内部文本编码由字体决定,HTTP头中的
charset=utf-8对PDF内容没有影响,因此之前的尝试无法解决问题。
解决方案
方案1:显式指定包含美元符号的字体(推荐)
不要依赖系统默认字体,在生成PDF的代码中显式加载支持$符号的字体,确保跨环境一致:
// 使用iText自带的Helvetica字体(非嵌入) BaseFont baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont, 12); // 添加文本时使用该字体 document.add(new Paragraph("$100.00", font));
如果需要彻底避免环境依赖,可将字体文件(如arial.ttf)放在项目resources/fonts目录下,嵌入到PDF中:
// 加载自定义字体并嵌入 BaseFont baseFont = BaseFont.createFont("fonts/arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); Font font = new Font(baseFont, 12);
方案2:在Ubuntu服务器安装缺失字体
通过安装包含美元符号的字体包,修复系统字体缺失问题:
sudo apt-get install fonts-dejavu-core
安装后重启应用即可。此方案依赖服务器环境,稳定性不如方案1。
方案3:升级iText版本(建议)
iText 2.1.7发布于2009年,存在大量已知问题和安全漏洞。建议升级到最新的iText 7版本(注意API与2.x差异较大,需修改代码),新版本字体处理逻辑更稳定,能从根源避免这类环境依赖问题。
内容的提问来源于stack exchange,提问作者Barry S
相关产品推荐
相关产品推荐

