Отсутствует изображение в сгенерированном PDF - PullRequest
0 голосов
/ 29 сентября 2019

Я пытаюсь преобразовать HTML-страницу в PDF с помощью библиотеки iText.У меня нет большого опыта, и я не могу добавить свое изображение в PDF.

Сначала я читаю шаблон HTML (который я использую для основы).Изображение размещается с тегом <img> следующим образом <img src="http://clipartmag.com/image/iron-man-face-drawing-6.png" class="avatar-image">.Я извлекаю класс Document из этого шаблона.Я добавляю нужный контент в экземпляр Document.После этого я извлекаю html и использую его для создания PDF.

String resumeFilePath = String.format(RESUME_FILE_PATH, userProfileBean.getFirstname(), userProfileBean.getLastname());
            Document resumeAsHtml = createHtmlDocument(userProfileBean);
            HtmlConverter.convertToPdf(resumeAsHtml.html(), new FileOutputStream(resumeFilePath));
            File newResume = new File(resumeFilePath);

На этапе тестирования я даже создал отдельную страницу HTML, чтобы увидеть, что все на месте - resumeAsHtml.html().На веб-странице было изображение на странице.Но когда я звоню

HtmlConverter.convertToPdf(
    resumeAsHtml.html(), new FileOutputStream(resumeFilePath));

, в созданном PDF-файле отсутствует изображение.Я также получаю 3 ошибки в журналах:

2019-09-29 10:06:22,678 ERROR c.i.s.c.p.s.CssParserStateController:495 - The rule @keyframes is unsupported. All selectors in this rule will be ignored.
2019-09-29 10:06:22,944 ERROR c.i.s.r.r.ResourceResolver:146 - Unable to retrieve image with given base URI (file:/Users/jklancic/dev/custom/resume/) and image source path (http://clipartmag.com/image/iron-man-face-drawing-6.png)
2019-09-29 10:06:22,947 ERROR c.i.h.a.i.DefaultHtmlProcessor:356 - Worker of type com.itextpdf.html2pdf.attach.impl.tags.DivTagWorker unable to process com.itextpdf.html2pdf.attach.impl.tags.ImgTagWorker

Есть идеи, что может быть не так?Вот шаблон, который уже содержит изображение:

<!DOCTYPE html>
<html>
<head>
<style>

#resume-header {
    margin-bottom: 25px;
}

#resume-body {
}

#clear {
    clear: both;
}

.header-left {
    width: 29%;
    height: 160px;
    float: left;
}

.header-right {
    padding-top: 10px;
    width: 70%;
    height: 160px;
    float: right;
}

.header-right h1,h2,h3 {
    text-align: left;
    font-family: verdana;
}

.header-right h1 {
    color: #4065a3;
    font-size: 34px;
    margin: 5px 0px 15px 0px;
}

.header-right h2 {
    font-size: 22px;
    margin: 5px 0px 5px 0px;
}

.header-right h3 {
    font-size: 10px
}

.avatar-image {
    display: block;
    margin-left: auto;
    margin-right: auto;
    height: 160px;
}

.info {
    margin: 0px 20px 0px 0px;
    font-family: verdana;
    font-size: 10px
}

span.section-header {
    color: #507fcc;
    font-family: verdana;
    font-size: 16px;
    margin: 0px 0px 0px 10px;
}

p.section-title {
    color: #000000;
    font-family: verdana;
    font-size: 12px;
}

p.section-subtitle {
    color: #9aa3b3;
    font-family: verdana;
    font-size: 12px;
    margin-left: 10px;
}

p.text {
    color: #000000;
    font-family: verdana;
    font-size: 10px;
}

ul.list {
    color: #000000;
    font-family: verdana;
    font-size: 10px;
    padding-left: 25px
}

div.web-profile {
    margin-top: 10px;
}

div.section-content {
    margin-bottom: 20px;
}

div.bottom-border {
    border-bottom: 1px solid #507fcc;
}

.primary {
    color: #507fcc;
}

.small-top-margin {
    margin: 2px 0px 0px 0px;
}

.small-bottom-margin {
    margin: 15px 0px 2px 0px;
}

</style>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css">

</head>
<body>

<div id="resume-header">
    <div class="header-left">
        <img src="http://clipartmag.com/image/iron-man-face-drawing-6.png" class="avatar-image">
    </div>
    <div class="header-right" id="basic-info">
    </div>
    <div id="clear"></div>
</div>
<div id="resume-body">
    <div class="bottom-border" id="education-section">
        <i class="fas fa-graduation-cap primary"></i><span class="section-header">Education</span>
    </div>

    <div class="bottom-border" id="job-section">
        <i class="fas fa-briefcase primary"></i><span class="section-header">Work</span>
    </div>

    <div class="bottom-border" id="skill-section">
        <i class="fas fa-pencil-ruler primary"></i><span class="section-header">Skills</span>
    </div>

</div>

</body>
</html>

1 Ответ

0 голосов
/ 29 сентября 2019

В iText очень много ошибок.Не комментируйте версию, которую вы используете, но у загрузчика ресурсов есть несколько проблем, которые необходимо исправить путем его перегрузки (он не знает, как загружать изображения из base64, он не знает, как загружать ресурсы с перенаправлением 302)., ...).

В вашем конкретном случае указана ошибка:

Невозможно получить изображение с заданным базовым URI (файл: / Users / jklancic / dev / custom/ resume /) и путь к источнику изображения (http://clipartmag.com/image/iron-man-face-drawing-6.png)

Это говорит о том, что iText пытается получить доступ к файлу адреса ": / Users / jklancic / dev / custom / resume / http://clipartmag.com/image/iron-man-face-drawing-6.png". Отладка на cisrrResourceResolver: 146 для подтверждения.

Если вам удастся выполнить обновление до новой версии, попробуйте сделать это, в противном случае вам следует перегрузить загрузчик ресурсов, чтобы исправить это.

Помните, сначала вы должны определить точную проблему (в настоящее время это проблема плохой комбинации базы + пути), в любом случае, я исправил множество связанных с этим проблем, реализуя нашу пользовательскую ITextUserAgent, следующим образом:

final ITextRenderer renderer = new ITextRenderer();
{
    final TextUserAgent userAgent = new TextUserAgent(renderer.getOutputDevice());
    renderer.getSharedContext().setUserAgentCallback(userAgent);
    userAgent.setSharedContext(renderer.getSharedContext());
}

Вы должны чертитьОставьте свой пользовательский TextUserAgent, чтобы решить вашу конкретную проблему (iText сейчас не бесплатный):

public class TextUserAgent extends ITextUserAgent {

    public TextUserAgent(ITextOutputDevice outputDevice) {
        super(outputDevice);
    }

    @Override
    public ImageResource getImageResource(final String uri) {
        final ImageResource legacy = super.getImageResource(uri);
        if (legacy != null && legacy.getImage() != null) {
            return legacy;
        }
        return alternativeImageResource(uri);
    }
...
...