Golang 使用 wkhtmltoimage 为网页截图或者生成图文

yufei       4 年, 9 月 前       3065

博客分享到朋友圈或者微博的时候经常是生成一个长的图文,这个一般是通过 wkhtmltoimage 来实现

今天我们就使用 Golang 搭配 wkhtmltoimage 命令来实现

  1. 首先是安装 wkhtmltoimage

    brew cask install wkhtmltopdf
    

    如果是其它系统,则直接访问 https://wkhtmltopdf.org/ 下载即可

  2. 然后就可以使用 os/exec 搭配 wkhtmltoimage 命令来实现了

    package main
    
    import (
        "bytes"
        "errors"
        "fmt"
        "image/jpeg"
        "image/png"
        "os"
        "os/exec"
        "strconv"
        "strings"
    )
    
    type ImageOptions struct {
        // BinaryPath the path to your wkhtmltoimage binary. REQUIRED
        //
        // Must be absolute path e.g /usr/local/bin/wkhtmltoimage
        BinaryPath string
        // Input is the content to turn into an image. REQUIRED
        //
        // Can be a url (http://example.com), a local file (/tmp/example.html), or html as a string (send "-" and set the Html value)
        Input string
        // Format is the type of image to generate
        //
        // jpg, png, svg, bmp supported. Defaults to local wkhtmltoimage default
        Format string
        // Height is the height of the screen used to render in pixels.
        //
        // Default is calculated from page content. Default 0 (renders entire page top to bottom)
        Height int
        // Width is the width of the screen used to render in pixels.
        //
        // Note that this is used only as a guide line. Default 1024
        Width int
        // Quality determines the final image quality.
        //
        // Values supported between 1 and 100. Default is 94
        Quality int
        // Html is a string of html to render into and image.
        //
        // Only needed to be set if Input is set to "-"
        Html string
        // Output controls how to save or return the image.
        //
        // Leave nil to return a []byte of the image. Set to a path (/tmp/example.png) to save as a file.
        Output string
    }
    
    func GenerateImage(options *ImageOptions) ([]byte, error) {
        arr, err := buildParams(options)
        if err != nil {
            return []byte{}, err
        }
    
        if options.BinaryPath == "" {
            options.BinaryPath = "/usr/local/bin/wkhtmltoimage"
        }
    
        cmd := exec.Command(options.BinaryPath, arr...)
    
        if options.Html != "" {
            cmd.Stdin = strings.NewReader(options.Html)
        }
    
        output, err := cmd.CombinedOutput()
    
        trimmed := cleanupOutput(output, options.Format)
    
        return trimmed, err
    }
    
    func buildParams(options *ImageOptions) ([]string, error) {
        a := []string{}
    
        if options.Input == "" {
            return []string{}, errors.New("Must provide input")
        }
    
        a = append(a, "-q")
        a = append(a, "--disable-plugins")
    
        a = append(a, "--format")
        if options.Format != "" {
            a = append(a, options.Format)
        } else {
            a = append(a, "png")
        }
    
        if options.Height != 0 {
            a = append(a, "--height")
            a = append(a, strconv.Itoa(options.Height))
        }
    
        if options.Width != 0 {
            a = append(a, "--width")
            a = append(a, strconv.Itoa(options.Width))
        }
    
        if options.Quality != 0 {
            a = append(a, "--quality")
            a = append(a, strconv.Itoa(options.Quality))
        }
    
        // 如果设置了 URL,则优先使用 URL
        if options.Input != "-" {
            // 如果使用 URL 则需要将 Html 参数置空
            options.Html = ""
        }
    
        a = append(a, options.Input)
    
        if options.Output == "" {
            a = append(a, "-")
        } else {
            a = append(a, options.Output)
        }
    
        return a, nil
    }
    
    func cleanupOutput(img []byte, format string) []byte {
        buf := new(bytes.Buffer)
        switch {
        case format == "png":
            decoded, err := png.Decode(bytes.NewReader(img))
            for err != nil {
                img = img[1:]
                if len(img) == 0 {
                    break
                }
                decoded, err = png.Decode(bytes.NewReader(img))
            }
            png.Encode(buf, decoded)
            return buf.Bytes()
        case format == "jpg":
            decoded, err := jpeg.Decode(bytes.NewReader(img))
            for err != nil {
                img = img[1:]
                if len(img) == 0 {
                    break
                }
                decoded, err = jpeg.Decode(bytes.NewReader(img))
            }
            jpeg.Encode(buf, decoded, nil)
            return buf.Bytes()
        }
        return img
    }
    
    func main() {
        html := "<html><head></head><body><p style='color:red;'>example</p></body></html>"
        c := ImageOptions{
            Input:  "https://www.twle.cn",
            Width:  640,
            Format: "png",
            Html:   html,
        }
        out, err := GenerateImage(&c)
        if err != nil {
            panic(err)
        }
        f, err := os.Create("example.png")
        if err != nil {
            panic(err)
        }
        defer f.Close()
        n2, err := f.Write(out)
        if err != nil {
            panic(err)
        }
        fmt.Printf("wrote %d bytes\n", n2)
    }
    
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.