Generate PDF Thumbnails for Document Previews with Go
Every document management system needs thumbnails. Users expect to see a visual preview before clicking on a file, whether it's a contract, invoice, or report. Without thumbnails, you're stuck showing generic PDF icons.
Generating PDF thumbnails locally requires heavy libraries like ImageMagick or Poppler. These add deployment complexity and consume server resources. For a Go backend, there's no clean native solution.
The simpler approach: convert PDF pages to images via API. Send the PDF URL, get back image URLs. No dependencies, no memory spikes, just clean HTTP calls.
Quick Example
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
apiToken := "YOUR_API_TOKEN"
apiURL := "https://apdf.io/api/pdf/file/to-image"
payload := map[string]interface{}{
"file": "https://pdfobject.com/pdf/sample.pdf",
"image_type": "jpeg",
"pages": "1",
"dpi": 150,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+apiToken)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
var result []map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("Thumbnail URL: %s\n", result[0]["file"])
}
The API returns an array of images, one per page. For a thumbnail, we only request page 1.
Real-World Scenario: Document Library API
You're building a document library for a SaaS app. When users upload PDFs, you need to generate thumbnails to display in the file browser. Here's a complete Go service that handles this:
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
const (
apiToken = "YOUR_API_TOKEN"
apiURL = "https://apdf.io/api/pdf/file/to-image"
)
type ThumbnailResult struct {
Page string `json:"page"`
File string `json:"file"`
Expiration string `json:"expiration"`
}
type ThumbnailRequest struct {
DocumentID string
PDFURL string
}
func generateThumbnail(pdfURL string) (*ThumbnailResult, error) {
payload := map[string]interface{}{
"file": pdfURL,
"image_type": "jpeg",
"pages": "1",
"dpi": 100, // Lower DPI for faster thumbnails
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+apiToken)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var results []ThumbnailResult
if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
return nil, err
}
if len(results) == 0 {
return nil, fmt.Errorf("no thumbnail generated")
}
return &results[0], nil
}
func main() {
// Documents that need thumbnails
documents := []ThumbnailRequest{
{DocumentID: "doc-001", PDFURL: "https://pdfobject.com/pdf/sample.pdf"},
{DocumentID: "doc-002", PDFURL: "https://ontheline.trincoll.edu/images/bookdown/sample-local-pdf.pdf"},
}
for _, doc := range documents {
fmt.Printf("Generating thumbnail for %s...\n", doc.DocumentID)
result, err := generateThumbnail(doc.PDFURL)
if err != nil {
fmt.Printf(" Error: %v\n", err)
continue
}
fmt.Printf(" Thumbnail: %s\n", result.File)
// In production: download and store this image in your storage
// The URL expires after 1 hour
}
}
Note: The thumbnail URLs are valid for 1 hour. Download and store them in your own storage (S3, local disk) for permanent use.
Choosing the Right Settings
The API offers several parameters to tune your thumbnails:
- image_type: Use
jpegfor photos/scans (smaller files),pngfor sharp text/diagrams - dpi: 72-100 for small thumbnails, 150 for medium previews, 300 for full-quality
- pages: Use
1for a single thumbnail, or1-3for a multi-page preview
// High-quality preview (e.g., document viewer)
payload := map[string]interface{}{
"file": pdfURL,
"image_type": "png",
"dpi": 200,
"pages": "1",
}
// Fast, small thumbnail (e.g., file browser grid)
payload := map[string]interface{}{
"file": pdfURL,
"image_type": "jpeg",
"dpi": 72,
"pages": "1",
}
// Multi-page preview carousel
payload := map[string]interface{}{
"file": pdfURL,
"image_type": "jpeg",
"dpi": 150,
"pages": "1-5",
}
Next Steps
Once you have thumbnails working, consider these enhancements:
- Extract first page: Use the Extract Pages endpoint to create a single-page preview PDF.
- Compress before converting: For large PDFs, use the Compress endpoint first to speed up thumbnail generation.