You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,但问题未解决。


问题原因

  1. 字体依赖环境差异:iText 2.1.7是非常老旧的版本,生成文本时若未显式指定字体,会依赖系统默认字体。MacOS默认字体(如Helvetica)完整包含$符号,但Ubuntu服务器的默认字体可能缺少该字符映射,或系统字符集配置导致编码转换错误,将$解析为¤。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:30:59