Печать изображений в формате bakgrounds из HTML-представления в PDF

#html #css #asp.net-mvc #razor

#HTML #css #asp.net-mvc #razor

Вопрос:

Я изо всех сил пытаюсь напечатать простой шаблон сертификата, мои текущие проблемы:

  1. Мне нужно установить два изображения для фона, главной страницы и обратной страницы. В настоящее время я настраиваю их, используя некоторое позиционирование css с помощью тегов.
  2. Когда я устанавливаю весь макет, они в порядке в представлении HTML, однако, как только я пытаюсь выполнить печать из браузера или из пользовательского плагина (rotativa wkhtmlpdf), макет перепутывается, и все форматирование исчезает.

Ниже приведен код: PS. @img_frente и @img_verso являются строками base64 для изображений в качестве фона.

  @@font-face {
            font-family: fonteMaior;
            src: url("../../Content/fonts/DINNextLTPro-Condensed.otf")
        }
/*        @@font-face {
            font-family: fonteMenor;
            src: url("../../Content/fonts/")
        }*/
        html {
            margin: 0 0;
            padding: 0;
        }

        body {
            margin: 0 0;
            font-family: fonteMaior;
            font-size: 28px;
            color: #464646;
        }

        .line {
            height: 20px;
            border-bottom: 1px solid #D1D1D1 !important;
            position: center;
        }

        * {
            -webkit-print-color-adjust: exact !important;
            page-break-inside: avoid !important;
        }

        .container {
            position: relative;
            text-align: center;
        }

        .mainText {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }

        .qrcode {
            position: absolute;
            bottom: 72px;
            left: 100px;
            border: 1px solid #D1D1D1 !important;
        }

        .registro {
            position: absolute;
            bottom: 120px;
            left: 265px;
        }

        .instrutor {
            position: absolute;
            bottom: 120px;
            left: 812px;
            width: 300px;
        }
        .verso {
            position: relative;

        }
        .conteudos {
            position: absolute;
            bottom: 430px;
            left: 135px;
        }

        @@media screen, print {
            html, body, #xxl {
                margin: 0;
                padding: 0;
                border: 0;
                font-family:fonteMaior;
                font-size:28;
            }

            #printable {
                margin: 0;
                padding: 0;
                border: 0;
                font-size: 14px;
            }

            img{
                display:inline;
            }
                #printable ~ * {
                    display: none;
                    -webkit-print-color-adjust: exact !important;
                    page-break-inside: avoid !important;
                }
        } 

Вид:

 <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="~/Scripts/js/library/jquery-1.11.0.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/bootstrap.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/jquery.appear.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/jquery.easing.min.js"></script>
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/library/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" media="all"href="~/Content/css/library/fontawesome.min.css">
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/md-font.css">
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/style.css">
        <script>
            window.load = function () {
                window.status = 'render-pdf';
            };
        </script>
        <style>
    
            CSS is above
        </style>
    
    </head>
    <body>
        <div id="frenteCert" class="frente container">
            <img src=@img_frente alt="imagem frente" />
            <div class="mainText text-justify" style="font-family:fonteMaior;">
                <span class="">
                    @ViewBag.nomeProfessor, confere a <b style="text-transform: uppercase;">@ViewBag.nomeAluno</b> o presente certificado, referente à sua participação no curso <b style="text-transform: uppercase;">@ViewBag.nomeCurso</b>,
                    concluído em @ViewBag.dataCertificado @*@ViewBag.dataConclusao*@ , com carga horária de @ViewBag.cargaHoraria horas.
                </span>
            </div>
            <div id="qrCode" class="qrcode">
                <img src="@ViewBag.QRCodeImage" alt="" style="height:150px;width:150px" />
            </div>
            <div id="dataEmissao" class="registro">
                <p style="font-size:24px; font-family:fonteMaior;">Curitiba, 21 de Maio de 2021.</p>
            </div>
            <div id="instrutor" class="instrutor">
                <div class="line"></div>
                <p class="text-center" style="text-align:center; font-size: 24px; font-family:fonteMaior;">INSTRUTOR</p>
            </div>
        </div>
        <div id="versoCert" class="verso container">
            <img src=@img_verso alt="imagem verso" />
            <div id="colunas" class="conteudos">
                @foreach (var item in ViewBag.conteudos)
                {
                    <p>@item.conteudo</p>
                }
            </div>
        </div>
    
    </body>
    </html>
 

Контроллер:
Это только та часть, где я вызываю генератор PDF, который работает, но не знаю, как лучше настроить.

 var viewPdf = new PartialViewAsPdf
{
    ViewName = "_GeraCertificado",
    RotativaOptions = { PageOrientation = Rotativa.Core.Options.Orientation.Landscape,
                        PageSize = Rotativa.Core.Options.Size.A4 },
    FileName = "certificado.pdf",
    Model = tbl_aluno_curso
};

if (isPdf != null amp;amp; isPdf == true)
{
    return viewPdf;
}
 

Вот пример изображения текущего вывода в html

Вывод в формате PDF — front

Вывод в формате PDF- обратно

Фронтальная

Назад

Комментарии:

1. Привет @CaioVC, вы пробовали использовать простой вид с макетом, добавляя CSS и скрипты через BundleConfig и вызывая метод ViewAsPdf? Какую версию Rotativa вы используете? Параметры Rotativa в вашем случае можно настроить проще, просто используя: return new PartialViewAsPdf { PageOrientation = Rotativa.Options.Orientation.Landscape, PageSize = Rotativa.Options.Size.A4, FileName = "certificado.pdf", Model = new tbl_aluno_curso() };

2. Что касается CCS, который вы указываете первым, где он размещен? На файл style.css, на который ссылаются как на ссылку или между тегами стиля в представлении? Если это возможно, я был бы очень полезен, если бы вы могли предоставить образец HTML, который работает вне вашей среды (пытался использовать ссылки cdnjs для начальной загрузки, jquery и плагинов, но, похоже, некоторые CSS все еще пропущены и / или версии не совпадают)? Obrigado.

3. Привет, Дэйв!! Большое вам спасибо за ваши отзывы, оказывается, мне удалось это сделать, изменив стиль макета на абсолютное / относительное позиционирование, вместо использования строк и столбцов, также я изменил фон на фон div, поэтому я настроил background-image в css, чтобы получить свой фон! Большое вам спасибо за конфигурации rotativa, хехех

4. Добро пожаловать. Рад слышать, что это работает! Помните, что вы можете опубликовать свой собственный ответ и пометить его как решение, если хотите поделиться необходимыми знаниями с сообществом 😉

5. Привет, Дэйв, ответ общий. Большое тебе спасибо, друг!

Ответ №1:

Я пришел к решению, рассматривая структуру div как родительскую / дочернюю с основным контейнером в каждом блоке сертификата, а затем выровнял их по относительному / абсолютному позиционированию. Полный код ниже:

PS. Я удалил бесполезные скрипты, а viewbags в src в тегах img и vars — это просто строки base64. Я надеюсь, что это может помочь людям!

                    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="~/Scripts/js/library/jquery-1.11.0.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/bootstrap.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/jquery.appear.min.js"></script>
        <script type="text/javascript" src="~/Scripts/js/library/jquery.easing.min.js"></script>
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/library/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/library/font-awesome.min.css">
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/md-font.css">
        <link rel="stylesheet" type="text/css" media="all" href="~/Content/css/style.css">

        <style>
    
            @@font-face {
                font-family: fonteMaior;
                src: url("../../Content/fonts/DINNextLTPro-Condensed.otf")
            }
    
            * {
                -webkit-print-color-adjust: exact !important;
                page-break-inside: avoid !important;
            }
    
            html {
                margin: 0 0;
                padding: 0;
            }
    
            body {
                margin: 0 0;
                font-family: fonteMaior !important;
                font-size: 28px;
                color: #464646;
                padding: 0;
            }
    
            .line {
                height: 20px;
                border-bottom: 1px solid #D1D1D1 !important;
                position: center;
            }
    
            .container {
                position: relative;
                text-align: center;
            }
    
            .mainText {
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
            }
    
            .qrcode {
                position: absolute;
                bottom: 72px;
                left: 95px;
                border: 1px solid #D1D1D1 !important;
            }
    
            .registro {
                position: absolute;
                bottom: 120px;
                left: 265px;
            }
    
            .instrutor {
                position: absolute;
                bottom: 120px;
                left: 775px;
                width: 300px;
            }
    
            #assinatura {
                position: absolute;
                z-index: 99;
                bottom: 35px;
                left: 65px;
                max-width: 280px;
                max-height: 110px;
                width: auto !important;
                height: auto !important;
            }
    
            .frente {
                background-image: url( @img_frente ) !important;
                background-repeat: no-repeat !important;
                background-position: top !important;
                background-size: contain !important;
                display: block !important;
                width: 1170px !important;
                height: 825px !important;
            }
            .verso {
                background-image: url( @img_verso ) !important;
                background-repeat: no-repeat !important;
                background-position: top !important;
                background-size: contain !important;
                display: block !important;
                width: 1170px !important;
                height: 825px !important;
            }
    
            .conteudos {
                position: absolute;
                bottom: 140px;
                left: 135px;
                display: inline-flex;
                flex-flow: column wrap;
                align-content: flex-start;
                height: 530px;
    /*            border: 1px solid blue !important;*/
            }
            .listConteudos{
    
            }
            ul {
                list-style-type: none;
                display: contents;
                float: left;
                flex-flow: column wrap;
                align-content: flex-start;
            }
    
            
            @@media screen, print {
                html, body {
                    margin: 0;
                    padding: 0;
                    border: 0;
                    font-family: fonteMaior !important;
                    font-size:28px;
                }
                .certContainer{
    
                }
                #printable {
                    margin: 0;
                    padding: 0;
                    border: 0;
                    font-size: 14px;
                }
    
                img{
                    display:inline;
                }
                    #printable ~ * {
                        display: none;
                        -webkit-print-color-adjust: exact !important;
                        page-break-inside: avoid !important;
                    }
            }
        </style>
    </head>
    <body>
        <div id="frenteCert" class="frente container">
            @*<img src=@img_frente alt="imagem frente" />*@
            <div class="mainText text-justify" style="font-family:fonteMaior;">
                <span class="">
                    @ViewBag.nomeProfessor, confere a <b style="text-transform: uppercase;">@ViewBag.nomeAluno</b> o presente certificado, referente à sua participação no curso <b style="text-transform: uppercase;">@ViewBag.nomeCurso</b>,
                    concluído em @ViewBag.dataConclusao, com carga horária de @ViewBag.cargaHoraria horas.
                </span>
            </div>
            <div id="qrCode" class="qrcode">
                <img src="@ViewBag.QRCodeImage" alt="" style="height:150px;width:150px" />
            </div>
            <div id="dataEmissao" class="registro">
                @if (ViewBag.cidade != null amp;amp; ViewBag.estado != null)
                {
                    <p style="font-size:24px; font-family:fonteMaior;">@ViewBag.cidade - @ViewBag.estado, @ViewBag.dataCertificado.</p>
                }
                else
                {
                    <p style="font-size:24px; font-family:fonteMaior;">CIDADE - UF, @ViewBag.dataCertificado.</p>
                }        </div>
            <div id="instrutor" class="instrutor">
                @if (ViewBag.assinatura != null)
                {
                    <img id="assinatura" src=@ViewBag.assinatura alt="" />
                }
                else
                {
                    <img id="assinatura" src=@signature alt="" style="height:75px;width:280px" />
                }
    
                <div class="line"></div>
                <p class="text-center" style="text-align:center; font-size: 24px; font-family:fonteMaior;">INSTRUTOR</p>
            </div>
        </div>
        <div id="versoCert" class="verso container" style="text-align:unset !important">
            @*<img src=@img_verso alt="imagem verso" />*@
            <div id="colunas" class="conteudos" style="width: 200px !important">
                <ul class="listConteudos">
                    @foreach (var item in ViewBag.conteudos)
                    {
                        <li style="font-family:fonteMaior; font-size: 18px !important; margin-right: 15px !important;">@item.conteudo</li>
                    }
                </ul>
            </div>
        </div>
    </body>
    </html>