Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tika Bundle Laravel Package

funstaff/tika-bundle

A Symfony bundle that integrates Apache Tika to extract text and metadata from documents such as PDFs, Office files, and images. It provides service configuration and a simple way to add content extraction to PHP applications, useful for search indexing and document processing workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you composer require anything: funstaff/tika-bundle is a Symfony bundle — it ships *Bundle classes, DependencyInjection/Extension config, and service definitions compiled into a Symfony kernel. Laravel has no bundle concept, no container extension, no config/packages/*.yaml. If you install it in a Laravel app, the only thing you can actually use is the underlying Tika client it wraps (typically vaites/php-apache-tika). The bundle layer is dead weight. Treat this repo as prior art, not a dependency.

What to look at first: the bundle's Resources/config/services.yml and the underlying client API. That's where the only real knowledge lives — how to configure the Tika binary path, how to configure JAR options (e.g. -Xmx, -t), and the two calls you'll actually make: extract text, extract metadata.

Prerequisites (the part the bundle doesn't solve for you):

  • A JVM on the host/container.
  • Either tika-app.jar on disk, or a running tika-server container (recommended).
  • On Laravel: vaites/php-apache-tika (the PHP client the bundle wraps), or nothing at all — just Http::timeout(30)->post('http://tika:9998/tika', ...) against a tika-server container.

First use case — get it working end-to-end in a day:

  1. docker run -p 9998:9998 apache/tika:latest (pin the tag — see Gotchas).
  2. Write a TextExtractor service in app/Services/ that hits PUT /tika (plain text) and PUT /meta (metadata) via Http::client(). ~50–80 lines, all yours.
  3. Bind it as a singleton in a service provider, or just resolve it via the container.
  4. Job: ExtractDocumentText queued on a dedicated extraction queue.
  5. Test with one real PDF from your users — not a synthetic one.

If you only need the spike, skip the jar and shell-out entirely. The container + HTTP client path is smaller, safer, and testable. That spike is your production design.

Implementation Patterns

Interface-first, so you can swap engines later.

interface TextExtractor {
    public function text(string $path): string;
    public function metadata(string $path): array;
    public function mimeType(string $path): string;
}

Bind TikaTextExtractor in a DocumentServiceProvider. This is the one thing worth copying from the bundle: it exists to produce exactly this seam in a DI container.

Config, not hardcoded. Publish a config/documents.php with tika.url, tika.timeout, tika.max_bytes, tika.max_pages. The bundle exposes these as bundle config; in Laravel they're a config file and env vars. Same idea, your lifecycle.

Always extract in a queue job. Extraction is multi-second on real documents. Never do it inline in a controller.

class ExtractDocumentText implements ShouldQueue {
    public $queue = 'extraction';
    public $timeout = 120;
    public $tries = 3;
    public $backoff = [5, 30, 120];
    // handle(): $text = $this->extractor->text($this->storedPath());
}

Detect MIME server-side. The whole point of putting a document through Tika is that $_FILES['f']['type'] and the extension are attacker-controlled. Call mimeType() and gate on that (allowlist PDF/DOCX/XLSX/PPTX/HTML), then extract. This is often the first integration the developer actually needs — validation, not text.

Store extracted text; don't re-extract. Add documents.extracted_text (longtext) + documents.metadata (json) + documents.extracted_at. The Tika call is the expensive part; make it idempotent and re-runnable.

RAG / search pipeline shape:

upload → MIME gate → queue job → tika-server → text → chunk → embed → vector store
                                   └→ metadata → DB (author, pages, created)

Metadata harvesting pattern. PUT /meta returns XHTML; parse with DOMDocument + XPath into a flat array (Content-Type, dc:creator, meta:page-count, pdf:PDFVersion). Keep it normalized — every format reports different keys.

Sync vs async split:

  • Small metadata-only probes (MIME detection on upload) → sync, short timeout.
  • Full text extraction on any real file → queued, long timeout, retries.
  • Bulk backfill during migration → queued in batches, throttle concurrency.

Fail-open vs fail-closed. Decide per feature. Search indexing can tolerate a failed extraction (log + retry). Compliance/KYC intake should block the upload. Encode this in the job/controller, not in the extractor.

Gotchas and Tips

  • You will not get this bundle running on Laravel. Its Symfony constraints (typically symfony/framework-bundle, old PHP pins) will fight Composer resolution. --ignore-platform-reqs is a symptom, not a fix. Use vaites/php-apache-tika or plain HTTP.
  • The jar-per-call path is deceptively slow. JVM startup is ~1–3s before parsing. Fine for a CLI batch backfill; catastrophic in a web request. Use tika-server for anything user-facing, and health-check the container independently of the PHP app.
  • OOM on real PDFs. Large, malformed, or scanned PDFs saturate Tika's heap. Set -Xmx explicitly, cap upload size (e.g. 20–50MB), cap page count, and set a hard per-request timeout. Without these, one bad file takes out a worker.
  • Silent empty extraction. A 200 response with Content-Length: 0 is not success — it's a parser that gave up. Assert non-empty text on formats you expect to have text; log the raw length and Content-Type on every call.
  • JVM hangs on adversarial/corrupt files. Timeouts at the HTTP client are necessary but not sufficient — a hung request holds a worker. Add a circuit breaker and a dead-letter queue. If shelling out (not recommended), reap zombie java processes.
  • Encoding surprises. Extracted text is not guaranteed NFC-normalized, may contain form feeds, zero-width characters, or BOMs. Normalize (Normalizer::normalize, strip control chars) before indexing or chunking for embeddings.
  • MIME detection is not always what you expect. HTML files sometimes report as text, images as application/octet-stream if Tika can't sniff them, and Office XML wrappers can differ by generator. Keep a small allowlist of accepted types and a fallback message — don't let octet-stream silently reach a "validated" state.
  • Pin the Tika image tag. apache/tika:latest will rotate under you, change parser behavior, and reintroduce CVEs. Pin to a specific minor (e.g. apache/tika:2.9.2), patch deliberately, and track Tika parser CVEs yourself — the bundle has zero security-patch cadence.
  • Zero support surface. 1 star, 0 dependents, no CI signals. If you do pull the bundle in anywhere for reference, budget to fork and own it — there will be no upstream fixes for PHP 8.x compatibility, Symfony version bumps, or CVEs. Same applies to vaites/php-apache-tika if that's your chosen client — pin it, wrap it behind your interface, and be ready to replace it.
  • Extension points worth copying from the bundle: the binary/JAR path config and the "extract text / extract metadata" service methods. Everything else (DI wiring, kernel hooks, config tree) is Symfony-specific and does not transfer.
  • Debugging a failed extraction: log (file hash, format-detected, bytes-in, bytes-out, ms, http-status) on every call. When a user says "search can't find my document," you want the answer in one query, not a re-run.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core