Go语言 wkhtmltopdf不在PDF上显示页脚

sshcrbum  于 2023-06-19  发布在  Go
关注(0)|答案(1)|浏览(190)

bounty还有16小时到期。此问题的答案有资格获得+50声望奖励。girish希望引起更多关注这个问题。

我正在使用wkhtmltopdf库生成PDF,当它托管在服务器上时,我无法获得PDF文档的页脚。它在我的本地系统上工作正常。我使用下面的代码来设置页脚。

func HTMLtoPDF(html string, someID int64, templatePath string) (*wkhtml.PDFGenerator, error) {
pdfg, err := wkhtml.NewPDFGenerator()
if err != nil {
    return nil, err
}
page := wkhtml.NewPageReader(strings.NewReader(util.FilterSmartQuotesEtc(html)))
tempPath := path.Clean(fmt.Sprintf("%v/%s", templatePath, "footer.html"))
footerFilePath, err := getFooterFilePath(tempPath, someID)
if err != nil {
    return nil, err
}
page.FooterHTML.Set(footerFilePath)

pdfg.AddPage(page)
pdfg.MarginTop.Set(10)
pdfg.MarginBottom.Set(10)

// Create PDF document in internal buffer
err = pdfg.Create()

if err != nil {
    return nil, err
}

return pdfg, nil
}

func getFooterFilePath(templatePath string, someID int64) (string, error) {
tmpl, err := htmlTemplate.ParseFiles(templatePath)
if err != nil {
    return "", err
}

var buf bytes.Buffer
data := FooterData {
    SomeID: someID,
}
err = tmpl.Execute(&buf, data)
if err != nil {
    return "", err
}

// Save the rendered HTML to a temporary file
tmpFile, err := ioutil.TempFile("", "footer-*.html")
if err != nil {
    return "", err
}

if _, err := tmpFile.Write(buf.Bytes()); err != nil {
    return "", err
}
if err := tmpFile.Close(); err != nil {
    return "", err
}
return tmpFile.Name(), nil
}

我已经验证了在getFooterFilePath函数中创建了临时页脚文件,并且我的someID变量也被替换。我通过记录生成的临时页脚文件检查了这一点,我可以在日志中看到内容。我做错什么了吗?任何帮助真的很感激

tp5buhyn

tp5buhyn1#

wkhtmltopdf具有--replace <name> <value>选项,可以在页眉和页脚中将name替换为value(可重复)。这是创建动态页眉和页脚的推荐方法。希望它能解决这个问题。参考:https://wkhtmltopdf.org/usage/wkhtmltopdf.txt
下面是演示:

package main

import (
    "os"
    "strconv"
    "strings"

    wkhtml "github.com/SebastiaanKlippert/go-wkhtmltopdf"
)

func HTMLtoPDF(html string, someID int64) (*wkhtml.PDFGenerator, error) {
    pdfg, err := wkhtml.NewPDFGenerator()
    if err != nil {
        return nil, err
    }
    page := wkhtml.NewPageReader(strings.NewReader(html))

    page.FooterHTML.Set("footer.html")

    // the following parameters are passed to footer.html in the query.
    page.Replace.Set("hello", "world")
    page.Replace.Set("my_id", strconv.Itoa(int(someID)))

    pdfg.AddPage(page)
    pdfg.MarginTop.Set(10)
    pdfg.MarginBottom.Set(10)

    err = pdfg.Create()

    if err != nil {
        return nil, err
    }

    return pdfg, nil
}

func main() {
    pdfg, err := HTMLtoPDF(html, 123457789)
    if err != nil {
        panic(err)
    }

    err = os.WriteFile("temp.pdf", pdfg.Bytes(), 0o644)
    if err != nil {
        panic(err)
    }
}

var html = `
<html>
    <body style="font-size:100pt;">
        Hello world!
    </body>
</html>
`

下面是footer. html文件:

<!DOCTYPE html>
<html>
  <head>
    <script>
      function subst() {
        var vars = {};
        var query_strings_from_url = document.location.search
          .substring(1)
          .split('&');
        for (var query_string in query_strings_from_url) {
          if (query_strings_from_url.hasOwnProperty(query_string)) {
            var temp_var = query_strings_from_url[query_string].split('=', 2);
            vars[temp_var[0]] = decodeURI(temp_var[1]);
          }
        }
        var css_selector_classes = [
          // these values are provided by wkhtmltopdf.
          'page',
          'frompage',
          'topage',
          'webpage',
          'section',
          'subsection',
          'date',
          'isodate',
          'time',
          'title',
          'doctitle',
          'sitepage',
          'sitepages',

          // these values are provided by the "replace" option.
          'hello',
          'my_id',
        ];
        for (var css_class in css_selector_classes) {
          if (css_selector_classes.hasOwnProperty(css_class)) {
            var element = document.getElementsByClassName(
              css_selector_classes[css_class]
            );
            for (var j = 0; j < element.length; ++j) {
              element[j].textContent = vars[css_selector_classes[css_class]];
            }
          }
        }
      }
    </script>
  </head>
  <body style="border: 0; margin: 0" onload="subst()">
    <table style="border-top: 1px solid black; width: 100%">
      <tr>
        <td class="section"></td>
        <td class="hello"></td>
        <td class="my_id"></td>
        <td style="text-align: right">
          Page <span class="page"></span> of <span class="topage"></span>
        </td>
      </tr>
    </table>
  </body>
</html>

如果上述方法不起作用,或者您有兴趣找出临时文件方法的问题所在,我们可以先做这些事情来缩小问题范围:
1.运行strace -f /path/to/the/app > log.txt跟踪系统调用和信号。-f选项使其跟踪子进程(wkhtmltopdf在子进程中运行)。
1.最后一步的日志应该包含传递给wkhtmltopdf命令的选项。直接使用相同的选项运行wkhtmltopdf命令,看看是否有什么不同。
1.如果页脚被正确呈现,那么Go代码中有一些错误。可能是临时文件尚未准备好使用。
1.如果它没有任何区别,因为相同的命令在您的本地计算机上工作,这可能是与环境相关的问题。可能服务器上的wkhtmltopdf版本有bug;可能服务器没有所需的字体。
请提供log.txt和直接运行wkhtmltopdf的结果,以便我们决定下一步怎么做。

相关问题