问题描述
在将项目部署到服务器并运行在 Docker 容器中时,下载文件添加水印时,所有水印的中文字符均显示为“口口口口口”,而不是预期的中文文本。
问题产生原因
- Word文档使用ShapeObject来添加水印,这通常是因为Word的API支持将文本作为形状(Shape)来处理,并且word文件格式支持直接嵌入字体和样式。因此,可以直接在 Word 文档中添加文本水印,而不需要将其转换为图片。
- Excel和PowerPoint文档使用Font对象来创建字体,并将文本转化为图像来创建水印,以更加方便的控制水印的位置和样式。但Font对象的创建,依赖于服务器上已有的字体,因此如果服务器中没有对应的字体,java会使用默认字体,但是如果默认字体不支持中文,就可能会导致中文显示不正确。
解决方案1 :将字体放进项目中在代码中动态加载
获取字体文件包
需要那种字体可以直接在网上下载。
或者直接在自己的windows电脑上进行导出来,导出来的字体也是TTF后缀的字体文件。
进入电脑C盘的C:\Windows\Fonts 目录,里面是电脑的所有字体,直接将里面的文件复制出来使用即可。
将复制出来的字体文件放入resources目录下的fonts文件夹下
src ├── main │ ├── java │ └── resources │ └── fonts │ └── simsun.ttc
字体工具类
编写创建Font对象的字体工具类
import java.awt.*;
import java.io.InputStream;
import java.util.Objects;
/** * 字体工具类. */
public class FontUtils {
private FontUtils() {
}
/** * 从资源文件加载本地字体. * * @paramfontPath 字体路径, 相对 resources 目录的相对路径, 如 fonts/simsun.ttc * @paramfontStyle 字体风格, 可选值: Font.PLAIN, Font.BOLD, Font.ITALIC * @paramfontSize 字体大小 * @return字体 */public static Font loadLocalFont(String fontPath, int fontStyle, float fontSize) {
Font font;
try (InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontPath)) {
if (Objects.isNull(fontStream)) {
throw new FontException("Font resource is null.");
}
font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
font = font.deriveFont(fontStyle, fontSize);
} catch (Exception e) {
throw new FontException(e.getMessage(), e.getCause());
}
return font;
}
/** * 字体异常. */static class FontException extends RuntimeException {
public FontException(String message) {
super(message);
}
public FontException(String message, Throwable cause) {
super(message, cause);
}
}
}
使用
// 水印文字字体private static Font font= FontUtils.loadLocalFont("fonts/simsun.ttc", Font.BOLD, 20);
然后使用font对象创建的字体就可以正常表示中文了。
解决方案二:将字体导入到服务器中
进入服务器此目录下 /usr/share/fonts,将下载好的TTF字体包上传到服务器的 /usr/share/fonts目录下
然后执行命令
mkfontscale
mkfontdir
fc-cache
查看是否安装成功,执行命令:此命令是仅查找中文字体,如果想查询服务器所有字体,可以输入命令:fc-list
fc-list :lang=zh
执行命令能够查询到,就证明安装好了
如果想删除字体,直接将 /usr/share/fonts这个目录下对应的字体TTF包删除,然后执行命令:
sudo fc-cache -fv
理论上到这里导入字体应该就可以了。
但是由于我的项目是使用docker部署的,因此刚开始执行到这一步并没有解决我的问题。
后来想了想,应该还需要将字体文件拷贝到docker容器中的/usr/share/fonts/目录下。
其他可能执行的操作:
启动项目时指定编码utf8
ENTRYPOINT ["java", "-Dfile.encoding=utf-8","-jar","filesystem-netdisk.jar"]