Как использовать предоставленный шаблон при создании PDF - PullRequest
2 голосов
/ 11 марта 2019

Хорошо, так что я Go Go Lang с Echo Framework, чтобы попытаться построить PDF, который будет загружать данные из источника базы данных - этот бит будет позже.

Так вот, как я отрисовываю мой pdf html layout,

func (c *Controller) DataTest(ec echo.Context) error {
  return ec.Render(http.StatusOK, "pdf.html", map[string]interface{}{
    "name": "TEST",
    "msg":  "Hello, XXXX!",
  })
}

Вышеприведенная функция работает нормально и отображает HTML (я создал временный путь к функции).Теперь я хочу использовать эту функцию в качестве моего HTML-шаблона для создания моих PDF-файлов.

Так что я использую wkhtmltopdf и lib "github.com/SebastiaanKlippert/go-wkhtmltopdf"

Вот как я должен рендерить HTML вpdf,

html, err := ioutil.ReadFile("./assets/pdf.html")

if err != nil {
    return err
}

Но мне нужно иметь возможность обновить шаблон, поэтому я пытаюсь отрисовать страницу и перенести ее в pdf.

Однако EchoFramework возвращает тип ошибки, а не байты или строки типа, и я не уверен, как его обновить, чтобы отображаемый контент возвращался в байтах?

Спасибо,

UPDATE

page := wkhtmltopdf.NewPageReader(bytes.NewReader(c.DataTest(data)))

Именно так я сейчас и поступаю, данные - это просто HTML-строка, которая затем превращается в кусочек байтов для NewReader.

Это прекрасно работает, но я хотел превратить функцию DataTest в полностью отрисованную html-страницу Echo.Проблема в том, что когда вы возвращаете визуализированную страницу, она возвращается как тип ошибки.

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

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

, если вы хотите визуализировать html, используйте echo 'custom middleware.Я надеюсь, что это поможет вам.

main.go

package main

import (
    "bufio"
    "bytes"
    "errors"
    "fmt"
    "html/template"
    "io"
    "net"

    "net/http"

    "github.com/labstack/echo"
)

type TemplateRegistry struct {
    templates map[string]*template.Template
}

func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    tmpl, ok := t.templates[name]
    if !ok {
        err := errors.New("Template not found -> " + name)
        return err
    }
    return tmpl.ExecuteTemplate(w, "base.html", data)
}

func main() {
    e := echo.New()

    templates := make(map[string]*template.Template)
    templates["about.html"] = template.Must(template.ParseFiles("view/about.html", "view/base.html"))
    e.Renderer = &TemplateRegistry{
        templates: templates,
    }

    // add custom middleware
    // e.Use(PdfMiddleware)

    // only AboutHandler for Pdf
    e.GET("/about", PdfMiddleware(AboutHandler))

    // Start the Echo server
    e.Logger.Fatal(e.Start(":8080"))
}

// custom middleware
func PdfMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) (err error) {
        resBody := new(bytes.Buffer)
        mw := io.MultiWriter(c.Response().Writer, resBody)
        writer := &bodyDumpResponseWriter{Writer: mw, ResponseWriter: c.Response().Writer}
        c.Response().Writer = writer

        if err = next(c); err != nil {
            c.Error(err)
        }

        // or use resBody.Bytes()
        fmt.Println(resBody.String())
        return
    }
}

type bodyDumpResponseWriter struct {
    io.Writer
    http.ResponseWriter
}

func (w *bodyDumpResponseWriter) WriteHeader(code int) {
    w.ResponseWriter.WriteHeader(code)
}

func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {
    return w.Writer.Write(b)
}

func (w *bodyDumpResponseWriter) Flush() {
    w.ResponseWriter.(http.Flusher).Flush()
}

func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    return w.ResponseWriter.(http.Hijacker).Hijack()
}

func AboutHandler(c echo.Context) error {
    return c.Render(http.StatusOK, "about.html", map[string]interface{}{
        "name": "About",
        "msg":  "All about Boatswain!",
    })
}

view / about.html

{{define "title"}}
  Boatswain Blog | {{index . "name"}}
{{end}}

{{define "body"}}
  <h1>{{index . "msg"}}</h1>
  <h2>This is the about page.</h2>
{{end}}

view / base.html

{{define "base.html"}}
<!DOCTYPE html>
  <html>
    <head>
      <title>{{template "title" .}}</title>
    </head>
    <body>
      {{template "body" .}}
    </body>
  </html>
{{end}}
0 голосов
/ 14 марта 2019

Итак, насколько я понимаю, вы хотите:

  1. Рендеринг HTML из шаблона
  2. Преобразование HTML в PDF
  3. Отправить его как ответ HTTP?Эта часть не ясна из вашего вопроса, но на самом деле это не имеет значения.

Итак, причина, по которой Echo возвращает error, заключается в том, что он фактически не только выполняет рендеринг шаблона, но и отправляет ответклиенту.Если вы хотите сделать что-то еще в промежутке, вы не можете использовать этот метод из echo.

К счастью, echo не делает там ничего волшебного.Вы можете просто использовать стандартный шаблон пакета с тем же результатом.

func GetHtml(filename string, data interface{}) (string, error) {
    filedata, err := ioutil.ReadFile(filename)
    if err != nil {
        return "", err
    }

    asString := string(filedata)
    t, err := template.New("any-name").Parse(asString)
    if err != nil {
        return "", err
    }

    var buffer bytes.Buffer
    err = t.Execute(&buffer, data)
    if err != nil {
        return "", err
    }

    return buffer.String(), nil
}

Там у вас есть функция, которая возвращает string.Вы можете использовать buffer.Bytes(), чтобы иметь байтовый массив, если это предпочтительнее.

После этого вы можете делать все, что вам нужно, например конвертировать в PDF и записывать его обратно клиентам, используя echoCtx.Response().Writer().

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...