106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
package extractors
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
// PDFExtractor extracts text content from PDF files using pdftotext
|
|
type PDFExtractor struct {
|
|
pdftotextPath string
|
|
available bool
|
|
initError error
|
|
}
|
|
|
|
// NewPDFExtractor creates a new PDF extractor
|
|
func NewPDFExtractor() *PDFExtractor {
|
|
return &PDFExtractor{}
|
|
}
|
|
|
|
// Key returns the unique identifier for this extractor
|
|
func (e *PDFExtractor) Key() string {
|
|
return "pdf"
|
|
}
|
|
|
|
// Name returns the human-readable name for this extractor
|
|
func (e *PDFExtractor) Name() string {
|
|
return "PDF Text Extractor"
|
|
}
|
|
|
|
// SupportedMimeTypes returns the MIME types this extractor supports
|
|
func (e *PDFExtractor) SupportedMimeTypes() []string {
|
|
return []string{"application/pdf"}
|
|
}
|
|
|
|
// Init initializes the extractor by checking if pdftotext is available
|
|
func (e *PDFExtractor) Init() error {
|
|
// Check if pdftotext is available in PATH
|
|
path, err := exec.LookPath("pdftotext")
|
|
if err != nil {
|
|
e.available = false
|
|
e.initError = fmt.Errorf("pdftotext binary not found in PATH: %w", err)
|
|
return e.initError
|
|
}
|
|
|
|
e.pdftotextPath = path
|
|
e.available = true
|
|
e.initError = nil
|
|
return nil
|
|
}
|
|
|
|
// Extract extracts text content from a PDF file
|
|
func (e *PDFExtractor) Extract(ctx context.Context, filePath string) (string, error) {
|
|
if !e.available {
|
|
return "", fmt.Errorf("PDF extractor is not available: %w", e.initError)
|
|
}
|
|
|
|
// Open the PDF file
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to open file: %w", err)
|
|
}
|
|
defer func() { _ = file.Close() }()
|
|
|
|
// Create command to run pdftotext
|
|
// Use "-" to read from stdin and output to stdout
|
|
cmd := exec.CommandContext(ctx, e.pdftotextPath, "-", "-")
|
|
cmd.Stdin = file
|
|
|
|
// Capture stdout
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to create stdout pipe: %w", err)
|
|
}
|
|
|
|
// Start the command
|
|
if err := cmd.Start(); err != nil {
|
|
return "", fmt.Errorf("failed to start pdftotext: %w", err)
|
|
}
|
|
|
|
// Read all output
|
|
output, err := io.ReadAll(stdout)
|
|
if err != nil {
|
|
_ = cmd.Wait()
|
|
return "", fmt.Errorf("failed to read output: %w", err)
|
|
}
|
|
|
|
// Wait for command to complete
|
|
if err := cmd.Wait(); err != nil {
|
|
return "", fmt.Errorf("pdftotext failed: %w", err)
|
|
}
|
|
|
|
return string(output), nil
|
|
}
|
|
|
|
// GetInitError returns the initialization error if any
|
|
func (e *PDFExtractor) GetInitError() error {
|
|
return e.initError
|
|
}
|
|
|
|
// IsAvailable returns whether the extractor is available
|
|
func (e *PDFExtractor) IsAvailable() bool {
|
|
return e.available
|
|
}
|