Go ChromeDP ignores any external or internal css during printing to pdf and uses only those, that in html file ONLY

huangapple go评论78阅读模式
英文:

Go ChromeDP ignores any external or internal css during printing to pdf and uses only those, that in html file ONLY

问题

Go ChromeDP不使用任何CSS,无论是内部还是外部样式(只使用在HTML中编写的样式,不使用其他文件)。我使用以下方法将HTML文件添加到chromedp中:

page.SetDocumentContent(frameTree.Frame.ID, string(buf.Bytes())).Do(ctx)

然后使用以下代码将其转换为PDF:

buf, _, err := page.PrintToPDF().Do(ctx)
if err != nil {
    return err
}
_, err = outputBuf.Write(buf)
if err != nil {
    return err
}

但是生成的PDF没有样式(即使使用外部CSS文件服务器)。我尝试使用page.GetResourceTree().Do(ctx) + css.CreateStyleSheet(resourceTree.Frame.ID).Do(ctx)来添加CSS,并使用以下代码设置样式:

css.SetStyleSheetText(stylesheet, `.c {
     color: red;
     font-size: 30px;
     background-color: aqua;
}`).Do(ctx)

这样可以工作,但是每次生成PDF时都需要这样做,特别是在使用html/template的情况下。也许有一种简单的方法可以将外部CSS添加到单个HTML文件中。你觉得呢?

谢谢任何回答。

Bohdan

我想使用chromedp将带有外部CSS、图像和字体的Go模板转换为PDF,但它忽略了主HTML文件之外的任何内容。

英文:

Go ChromeDP not using any css either internal or external styles (only those, that was written in html, not other file). I using method

page.SetDocumentContent(frameTree.Frame.ID, string(buf.Bytes())).Do(ctx)

to add html file to chromedp, and

buf, _, err: = page.PrintToPDF().Do(ctx)
if err != nil {
    return err
}
_, err = outputBuf.Write(buf)
if err != nil {
    return err
}

to print to pdf, but pdf in result not styled (even with external css fileserver). I tried to add it with page.GetResourceTree().Do(ctx) + css.CreateStyleSheet(resourceTree.Frame.ID).Do(ctx) +

css.SetStyleSheetText(stylesheet, `.c {
     color: red;
     font-size: 30px;
     background-color: aqua;
}
`).Do(ctx)

and it worked, but it sad to use it every time I want generate pdf, especially in my case, because I am using html from html/template. Maybe there are easy way to add external css into single html file? What do you think?

Thanks for any answer

Bohdan

I want to convert go template with external css, images and font into pdf using chromedp, but it ignored anything beyond main html file.

答案1

得分: 4

请注意,外部资源需要时间加载。您应该等待它们加载完成。当页面准备好时,会触发Page.loadEventFired事件。因此,我们可以等待此事件,然后打印页面。请参考下面的示例代码:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"time"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 模拟网络延迟
		time.Sleep(2 * time.Second)
		w.Header().Set("Content-Type", "text/css")
		fmt.Fprint(w, `h1 {font-size: 100pt; color: red;}`)
	}))
	defer ts.Close()

	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// 构建您的HTML
	html := `<html>
    <head>
        <link rel="stylesheet" href="%s/style.css">
    </head>
    <body>
        <h1> Hello World! </h1>
    </body>
</html>
`

	var wg sync.WaitGroup
	wg.Add(1)
	if err := chromedp.Run(ctx,
		chromedp.Navigate("about:blank"),
		// 设置监听器以监听page.EventLoadEventFired事件
		chromedp.ActionFunc(func(ctx context.Context) error {
			lctx, cancel := context.WithCancel(ctx)
			chromedp.ListenTarget(lctx, func(ev interface{}) {
				if _, ok := ev.(*page.EventLoadEventFired); ok {
					wg.Done()
					// 移除事件监听器
					cancel()
				}
			})
			return nil
		}),
		chromedp.ActionFunc(func(ctx context.Context) error {
			frameTree, err := page.GetFrameTree().Do(ctx)
			if err != nil {
				return err
			}
			return page.SetDocumentContent(frameTree.Frame.ID, fmt.Sprintf(html, ts.URL)).Do(ctx)
		}),
		// 等待page.EventLoadEventFired事件
		chromedp.ActionFunc(func(ctx context.Context) error {
			wg.Wait()
			return nil
		}),
		chromedp.ActionFunc(func(ctx context.Context) error {
			buf, _, err := page.PrintToPDF().Do(ctx)
			if err != nil {
				return err
			}
			return os.WriteFile("sample.pdf", buf, 0644)
		}),
	); err != nil {
		log.Fatal(err)
	}

	log.Println("完成!")
}

参考:https://github.com/chromedp/chromedp/issues/1152.

英文:

Please note that external resources take time to load. You should wait for them to be loaded. When the page is ready, the Page.loadEventFired event is raised. So we can wait for this event and print the page afterward. See the demo below:

package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;net/http/httptest&quot;
	&quot;os&quot;
	&quot;sync&quot;
	&quot;time&quot;

	&quot;github.com/chromedp/cdproto/page&quot;
	&quot;github.com/chromedp/chromedp&quot;
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Simulate a network latency.
		time.Sleep(2 * time.Second)
		w.Header().Set(&quot;Content-Type&quot;, &quot;text/css&quot;)
		fmt.Fprint(w, `h1 {font-size: 100pt; color: red;}`)
	}))
	defer ts.Close()

	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// construct your html
	html := `&lt;html&gt;
    &lt;head&gt;
        &lt;link rel=&quot;stylesheet&quot; href=&quot;%s/style.css&quot;&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt; Hello World! &lt;/h1&gt;
    &lt;/body&gt;
&lt;/html&gt;
`

	var wg sync.WaitGroup
	wg.Add(1)
	if err := chromedp.Run(ctx,
		chromedp.Navigate(&quot;about:blank&quot;),
		// setup the listener to listen for the page.EventLoadEventFired
		chromedp.ActionFunc(func(ctx context.Context) error {
			lctx, cancel := context.WithCancel(ctx)
			chromedp.ListenTarget(lctx, func(ev interface{}) {
				if _, ok := ev.(*page.EventLoadEventFired); ok {
					wg.Done()
					// remove the event listener
					cancel()
				}
			})
			return nil
		}),
		chromedp.ActionFunc(func(ctx context.Context) error {
			frameTree, err := page.GetFrameTree().Do(ctx)
			if err != nil {
				return err
			}
			return page.SetDocumentContent(frameTree.Frame.ID, fmt.Sprintf(html, ts.URL)).Do(ctx)
		}),
		// wait for page.EventLoadEventFired
		chromedp.ActionFunc(func(ctx context.Context) error {
			wg.Wait()
			return nil
		}),
		chromedp.ActionFunc(func(ctx context.Context) error {
			buf, _, err := page.PrintToPDF().Do(ctx)
			if err != nil {
				return err
			}
			return os.WriteFile(&quot;sample.pdf&quot;, buf, 0644)
		}),
	); err != nil {
		log.Fatal(err)
	}

	log.Println(&quot;done!&quot;)
}

Reference: https://github.com/chromedp/chromedp/issues/1152.

huangapple
  • 本文由 发表于 2023年3月29日 15:50:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75874509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定