Добавляем экспорт в PDF на сайт под BeeGo -2


Все делается достаточно банально и просто. С поиском решения весь процесс занял не более пары часов. Правда нужно использовать сторонние средства (уже слышу ехидные усмешки разработчиков node.js). К сожалению, полноценного процесса на Go на момент написания я не нашел. Используем wkhtmltopdf.

Он понравился прежде всего за простоту установки.

К примеру для Ubuntu:

apt-get install wkhtmltopdf
apt-get install xvfb
echo -e '#!/bin/bash\nxvfb-run -a --server-args="-screen 0, 1024x768x24" /usr/bin/wkhtmltopdf -q $*' > /usr/bin/wkhtmltopdf.sh
chmod a+x /usr/bin/wkhtmltopdf.sh
ln -s /usr/bin/wkhtmltopdf.sh /usr/local/bin/wkhtmltopdf

Но на сервере тогда нужно будет настраивать виртуальный xserver. Проще всего это делать с помощью утилиты xvfb.

Но можно скачать с сайта wkhtmltopdf готовую сборку и установить с помощью команды

sudo dpkg -i name_packet.deb

Тогда не нужно настраивать никаких виртуальных X-ов.

Установка библиотеки в Go

go get github.com/SebastiaanKlippert/go-wkhtmltopdf

Ранее мы предусмотрительно создали специальный BaseController, в котором описываем общие функции. Как результат здесь мы можем глобально переопределить некоторые методы для всех наших контроллеров.

Итак, в BaseController.go добавляем функцию

func (b *BaseController) Render() error {
    if !b.EnableRender {
        return nil
    }
    rb, err := b.RenderBytes()
    if err != nil {
        return err
    }

    export := b.GetString("export")
    if export == "pdf" {
        b.Ctx.Output.Header("Content-Type", "application/pdf; charset=utf-8")
        return b.Ctx.Output.Body(ToPDF(rb))
    }
    if b.Ctx.ResponseWriter.Header().Get("Content-Type") == "" {
        b.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
    }

    return b.Ctx.Output.Body(rb)
}

С помощью ее мы переопределим стандартную функцию вывода контекста на нашу, в которой мы смотрим, есть ли параметр «export» и значение этого параметра «pdf».

Так же саму функцию ToPDF() я вынес в отдельный файл pdf.go в папке «controllers»

package controllers

import (
    "bytes"
    "log"

    "github.com/astaxie/beego"

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

// ToPDF ...
// Generate PDF document from HTML
func ToPDF(htmlStr []byte) []byte {

    // Create new PDF generator
    pdfg, err := wkhtmltopdf.NewPDFGenerator()
    if err != nil {
        log.Fatal(err)
    }

    pdfg.Dpi.Set(600)
    pdfg.NoCollate.Set(false)
    pdfg.PageSize.Set(wkhtmltopdf.PageSizeA4)
    pdfg.MarginBottom.Set(40)

    page1 := wkhtmltopdf.NewPageReader(bytes.NewReader(htmlStr))

    pdfg.AddPage(page1)

    // Create PDF document in internal buffer
    err = pdfg.Create()
    if err != nil {
        beego.Trace(err)
    }

    // Return buffer contents
    return pdfg.Bytes()

}

Если сжато, то здесь мы подключаем нашу библиотеку (именуем ее как wkhtmltopdf для удобства). В самой функции создаем новый документ, определяем нужное нам разрешение (Dpi) и размер страницы. Создаем страницу из содержимого, принимаемого через параметр. Добавляем полученную страницу в документ. Запускаем генерацию документа через «Create» и отдаем результат.

Таким образом все содержимое перед выводом можно экспортировать в pdf. Достаточно в адресе странички набрать bygolang.org?export=pdf.

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

Оригинал статьи посмотреть а так же проверить как работает данный способ можно здесь.




К сожалению, не доступен сервер mySQL