如何使用Go语言将图片转换为PDF文档?——网站图片下载自动转PDF工具开发疑问
Hey there! I totally get the frustration—finding clear docs for batch image-to-PDF in Go can be tricky, especially when most libraries seem focused on the reverse. Since Python was too slow for your use case, let's build this efficiently with Go using tools you've already looked at (plus some clear, working examples):
Solution 1: Using gopdf (Full Control Over Page Sizes)
gopdf is powerful for custom PDF generation, and with a little extra code, it handles batch image conversion seamlessly.
Step 1: Install the dependency
go get github.com/signintech/gopdf
Step 2: Full Working Code
This script will walk through your image directory, add each image as a properly sized PDF page, and export a single PDF:
package main import ( "fmt" "image" _ "image/jpeg" // Required to decode JPEGs _ "image/png" // Required to decode PNGs "os" "path/filepath" "github.com/signintech/gopdf" ) func main() { // Update these paths to match your setup imageDirectory := "./your-images-folder" outputPath := "./converted-images.pdf" // Initialize PDF with default A4 (we'll adjust pages per image) pdf := gopdf.GoPdf{} pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) // Walk through all files in the image directory err := filepath.Walk(imageDirectory, func(path string, info os.FileInfo, err error) error { if err != nil { return err } // Skip directories and non-image files if info.IsDir() { return nil } ext := filepath.Ext(path) if ext != ".jpg" && ext != ".jpeg" && ext != ".png" { return nil } // Open and decode the image to get its dimensions file, err := os.Open(path) if err != nil { fmt.Printf("Skipping %s: failed to open - %v\n", path, err) return nil } defer file.Close() img, _, err := image.Decode(file) if err != nil { fmt.Printf("Skipping %s: failed to decode - %v\n", path, err) return nil } imgWidth := float64(img.Bounds().Dx()) imgHeight := float64(img.Bounds().Dy()) // Calculate scaling to fit image within A4 (optional, remove if you want full-size pages) a4Width, a4Height := 595.28, 841.89 // A4 dimensions in points scale := min(a4Width/imgWidth, a4Height/imgHeight) if scale < 1 { imgWidth *= scale imgHeight *= scale } // Add a new page sized to fit the image pdf.AddPageWithSize(gopdf.PageSize{W: imgWidth, H: imgHeight}) // Draw the image onto the page if err := pdf.Image(path, 0, 0, &gopdf.Rect{W: imgWidth, H: imgHeight}); err != nil { fmt.Printf("Skipping %s: failed to add to PDF - %v\n", path, err) } return nil }) if err != nil { fmt.Printf("Error processing directory: %v\n", err) return } // Save the final PDF if err := pdf.WritePdf(outputPath); err != nil { fmt.Printf("Failed to save PDF: %v\n", err) return } fmt.Printf("Success! PDF saved to %s\n", outputPath) } // Helper to get the smaller of two floats func min(a, b float64) float64 { if a < b { return a } return b }
Key Notes:
- We explicitly register JPEG/PNG decoders (the standard library requires this to decode image files)
- The script skips invalid files instead of crashing, so it's robust for messy directories
- You can remove the scaling logic if you want each PDF page to match the exact size of the source image
Solution 2: Using Maroto (Simpler, Layout-Focused)
If you prefer cleaner code without manual size calculations, Maroto works great—it's built for report generation but handles images effortlessly.
Step 1: Install the dependency
go get github.com/johnfercher/maroto/v2
Step 2: Full Working Code
This will create a single PDF with each image centered on its own A4 page:
package main import ( "os" "path/filepath" "github.com/johnfercher/maroto/v2" "github.com/johnfercher/maroto/v2/pkg/components/image" "github.com/johnfercher/maroto/v2/pkg/config" "github.com/johnfercher/maroto/v2/pkg/props" ) func main() { imageDirectory := "./your-images-folder" outputPath := "./maroto-output.pdf" // Initialize Maroto with A4 portrait orientation m := maroto.NewMaroto(config.Portrait, config.A4) m.SetPageMargins(10, 10, 10) // Add small margins around images // Collect all image paths first var imagePaths []string filepath.Walk(imageDirectory, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { ext := filepath.Ext(path) if ext == ".jpg" || ext == ".jpeg" || ext == ".png" { imagePaths = append(imagePaths, path) } } return nil }) // Add each image as a full-width row on a new page for _, path := range imagePaths { // Add a row that takes up most of the page height, center the image m.AddRow(277, image.NewFromFile(path, props.Rect{ Center: true, Percent: 90, // Image takes 90% of the row width })) m.AddPage() } // Remove the extra blank page added at the end if len(imagePaths) > 0 { m.RemovePage(m.GetPageCount()) } // Export the PDF if err := m.OutputFileAndClose(outputPath); err != nil { panic(err) } fmt.Printf("PDF saved successfully to %s\n", outputPath) }
Key Notes:
- Maroto handles page sizing and layout automatically, so you don't have to calculate dimensions manually
- The
Percentproperty ensures images scale to fit the page without overflowing
Both of these solutions will be way faster than your Python implementation thanks to Go's compiled performance and efficient I/O handling. Pick the one that fits your need for control vs. simplicity!
内容的提问来源于stack exchange,提问作者D3crypt360

