2 votes

Les caractères UTF-8 n'apparaissent pas dans le PDF généré à partir du modèle html via flying saucer et thymeleaf

J'essaie de générer un pdf contenant des caractères chinois UTF-8 via la soucoupe volante et la feuille de thym. Mais le pdf généré ignore tous les caractères chinois (les caractères latins sont acceptés). Voici la configuration de Thymeleaf

@Configuration
public class ThymeleafConfig {

    @Bean
    public ClassLoaderTemplateResolver fileTemplateResolver(){
        ClassLoaderTemplateResolver fileTemplateResolver = new ClassLoaderTemplateResolver();
        fileTemplateResolver.setPrefix("templates/");
        fileTemplateResolver.setTemplateMode("HTML");
        fileTemplateResolver.setSuffix(".html");
        fileTemplateResolver.setCharacterEncoding("UTF-8");
        fileTemplateResolver.setOrder(1);
        return fileTemplateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(){
        SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
        springTemplateEngine.setEnableSpringELCompiler(true);
        springTemplateEngine.setTemplateResolver(fileTemplateResolver());
        return springTemplateEngine;
    }

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }
}

Comme vous pouvez le voir, j'ai défini le codage des caractères à UTF-8 pour le résolveur de modèles et le résolveur de vues.

Et l'utilitaire PDF pour générer des pdfs

public class PDFUtil {

    @Autowired
    private TemplateEngine templateEngine;

    public String createPdf(String templatename, String fileName, String modelName, Object model) throws IOException, DocumentException  {
        String fileNameUrl = "";
        Context ctx = new Context();

        ctx.setVariable(modelName, model);

        String processedHtml = templateEngine.process(templatename, ctx);
        FileOutputStream outputStream = null;

        try {
            final File outputFile = File.createTempFile(fileName, ".pdf");
            outputStream = new FileOutputStream(outputFile);

            ITextRenderer renderer = new ITextRenderer();
            ITextFontResolver resolver = renderer.getFontResolver();

            final ClassPathResource fonts = new ClassPathResource("fonts/PingFangSCRegular.ttf");
            String test = fonts.getFilename();
            resolver.addFont(fonts.getPath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

            renderer.setDocumentFromString(processedHtml);
            renderer.layout();
            renderer.createPDF(outputStream, false);
            renderer.finishPDF();
            FileSystemResource resource = new FileSystemResource(outputFile);
            fileNameUrl = resource.getURL().toString();
        }
        finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) { }
            }
        }

        return fileNameUrl;
    }
}

Ici, j'ai ajouté la police chinoise au résolveur.

Et voici l'en-tête html du modèle

<head th:fragment="html_head">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://unpkg.com/jsbarcode@latest/dist/JsBarcode.all.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/fontawesome.min.css" />
    <style type="text/css">
        @font-face {
            font-family: 'PingFang SC Regular';
            src: url('/fonts/PingFangSCRegular.ttf');
            -fs-pdf-font-embed: embed;
            -fs-pdf-font-encoding: Identity-H;
        }
    </style>

</head>

J'ai donc essayé de déclarer que le jeu de caractères est UTF-8 et que la famille de polices est PingFang SC Regular. Mais sans surprise, cela ne fonctionne pas.

Voici la dépendance maven que j'ai ajoutée à mon projet springboot

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>9.1.22</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.13.3</version>
        </dependency>

Le corps html que je veux rendre

<body>
    <div th:fragment="header(model)">
        <div class="row">
            <div class="col-4">
                <img id="barcode" alt="111"/>
            </div>
            <div class="col-4">
                <h3>aaa[[${model.title}]]</h3>
                <p id="print-time">[[${model.printTime}]]</p>
            </div>
        </div>
    </div>
</body>

Et le résultat rendu enter image description here

Quelqu'un peut-il comprendre pourquoi le caractère UTF-8 n'apparaît pas dans le pdf généré ? Toute idée serait appréciée.

0voto

obourgain Points 2460

Dans votre modèle, vous déclarez la police de caractères, mais vous ne l'appliquez pas au contenu de la page.

Il suffit de déclarer que la police doit être utilisée :

body {font-family: 'PingFang SC Regular';}

De plus, vous n'avez pas besoin d'utiliser @font-face dans le modèle, étant donné que vous avez ajouté la police au moteur de rendu (à l'aide de resolver.addFont ).

Le code HTML suivant devrait fonctionner correctement :

<html>
    <head>
        <style>
            body {font-family: 'PingFang SC Regular';}
        </style>
    </head>
    <body>
        <h3></h3>
    </body>
</html>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X