在windows中使用this.class.getClassLoader().getResource("").getPath()
获取路径没问题,
在linux中提示找不到模板文件
解决办法:
如果直接读可以使用getClass().getClassLoader().getResourceAsStream(path)
想深入了解的小伙伴可以参考:jar读取资源配置文件,jar包内包外,以及包内读取目录的方法
如果想通过classpath下的templates文件夹获取可以配置freemarker。
@Configuration
public class FreeMarkerConfig {
@Autowired
protected FreeMarkerConfigurer configurer;
@PostConstruct
public void setSharedVariable() {
configurer.setTemplateLoaderPath("classpath:/templates/");
freemarker.template.Configuration config = null;
try {
config = configurer.createConfiguration();
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
config.setDefaultEncoding("UTF-8");
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
config.setLogTemplateExceptions(false);
config.setNumberFormat("#");
config.setDateFormat("yyyy/MM/dd");
config.setDateTimeFormat("yyyy-MM-dd HH:mm:ss");
configurer.setConfiguration(config);
}
}
由于作者对freemarker不是很熟,在网上也没有找到很好的配置,所以配置可能有其他缺陷或者修正的地方,还请麻烦大佬们帮忙指出,多谢。
Template template = freemarkerConfig.getConfiguration().getTemplate(fileName + ".ftl");
这样直接getTemplate就可以获取到classpath下的templates的模板。
增加依赖
com.itextpdf
itext-asian
5.2.0
增加类
/**
* 处理中文不显示和乱码问题
*/
class ChineseFontsProvider extends XMLWorkerFontProvider {
@Override
public Font getFont(final String fontname, String encoding, float size, final int style) {
try {
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
return new Font(bfChinese, size, style);
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
return super.getFont(fontname, encoding, size, style);
}
}
调用时选择字体为新加的类对象
XMLWorkerHelper.getInstance().parseXHtml(writer,document,
new ByteArrayInputStream(htmlString.getBytes()),
XMLWorkerHelper.class.getResourceAsStream("/default.css"),
Charset.forName("UTF-8"),new ChineseFontsProvider());
springcloud的版本问题,header中的ContentType为空导致。像下载文件,或者在controller中进行跳转时,都会出现这种情况。
这个bug在spring cloud gateway的github上作者已经说明的解决方案:将springcloud gateway升级至2.0.1或以上的版本即可,我之前使用的是2.0.0,对应springcloud的版本 为 Finchley.RELEASE
想深入了解的小伙伴可以参考:springcloud gateway nullpointerexception (NettyRoutingFilter)
如果因为部分原因不能换其他的版本(我就是这种情况),可以将导出pdf的流上传至oss,然后返回链接再下载。
如果想在分页时做处理
public class MyPdfPageEventHelperextends PdfPageEventHelper
可以继承PdfPageEventHelper,重写方法
并在调用
XMLWorkerHelper.getInstance().parseXHtml(writer,document,
new ByteArrayInputStream(htmlString.getBytes()),
XMLWorkerHelper.class.getResourceAsStream("/default.css"),
Charset.forName("UTF-8"),new ChineseFontsProvider());
前设置writer.setPageEvent(new MyPdfPageEventHelper());
itext
取出有图片的list,通过sourceImg获取他的长和宽,在满足某些条件的时候,设置属性,并把该属性应用到freemarker中。
collect.forEach(c -> {
BufferedImage sourceImg= null;
try {
sourceImg = ImageIO.read(new URL(c.getFileUrl()).openStream());
} catch (IOException e) {
e.printStackTrace();
}
if (sourceImg != null) {
int height = sourceImg.getHeight();
int width = sourceImg.getWidth();
if (width / height < 4 / 3) {
c.setHtmlExtend("height: 400px");
}
}
});
是个取巧的办法,找了很久都没有很好的解决办法,所以只能暂时使用这种,并且并不能确认100%是因为图片长导致的,因为有些比例1:1的图片,虽然很长但是会自动分页,调试了一波后使用4/3这种比较好(因需求不同,条件和css都不同),这里不是很规范,推荐写成常量判断。
最后,文章内有出错的地方麻烦大家帮忙指正,如果您有更好的解决办法请一定留言评论,说不定会帮到更多的人。多谢大家的阅读,非常感谢。
解决问题参考的非常好的文章:
java操作PDF之iText超入门
iText5使用HTML生成PDF设置重复表头和强制翻页
使用freemarker+itextpdf通过HTML模版导出PDF
可能有用的文章:
Freemarker如何使用jar中的模板