fix: use file path instead of stream for PDF thumbnail generation#4334
Conversation
Ghostscript requires a real seekable file path with a .pdf extension to
render PDF pages correctly. Using readImageFile() with an anonymous stream
causes "Page drawing error" for complex PDFs because Ghostscript cannot
seek back through the stream to resolve cross-references and object streams.
For local files, pass the file path directly to readImage('[0]').
For remote files, copy to a named temp file first.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…test 031 was already taken by configurable-webhooks. Renamed folder and updated all FR/NFR IDs, paths, and references to 038. Also includes post-implementation cleanup: Safe\fclose, Safe\tempnam, Safe\unlink imports replacing @Unlink suppression, and the testPdfUploadCreatesThumbnail regression test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughImagickHandler::load() now branches PDF vs non‑PDF. PDFs use a real filesystem path (native local, local Flysystem, or a named ChangesPDF Thumbnail Generation Fix
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/specs/4-architecture/features/038-pdf-thumbnail-fix/spec.md (1)
47-59:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd the required footer at the bottom of this spec.
This new markdown doc ends without the mandated
---+*Last updated: 2026-05-04*footer.As per coding guidelines, "
**/*.md: Use Markdown format for documentation" and "At the bottom of documentation files, add an hr line followed byLast updated: [date of the update]`."
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7154ea7d-f5f5-47c2-ba8d-32f7955a8fff
📒 Files selected for processing (5)
app/Image/Handlers/ImagickHandler.phpdocs/specs/4-architecture/features/038-pdf-thumbnail-fix/plan.mddocs/specs/4-architecture/features/038-pdf-thumbnail-fix/spec.mddocs/specs/4-architecture/features/038-pdf-thumbnail-fix/tasks.mdtests/ImageProcessing/Image/Handlers/PhotosAddHandlerImagickTest.php
- Use tempnam() + rename() to avoid leaving an orphaned placeholder file - Wrap stream copy in its own try/finally to guarantee fclose() runs - Move readImage() inside the outer try/finally so temp file is cleaned up regardless of where an exception is thrown - Add is_file() guard before unlink() in case creation failed early - Add Safe\rename import - Update spec/plan/tasks doc footers and stale last-updated dates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hi @mitpjones thank you for your PR. Can I just ask you to extract the content of the if ($is_pdf) into a private function and similar for the normal path in order to reduce the complexity of the function. Other than that LGTM. :) |
Reduces cyclomatic complexity of load() as requested in PR review. PDF and stream loading logic now live in dedicated private methods with their own resource cleanup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hi @ildyria, getting a bit late for me here now. I'll check tomorrow if you want any further changes. Thanks, |
PDF thumbnail generation requires Ghostscript as an Imagick delegate. Without it, readImage() on a PDF path fails silently and no thumbnail is produced, causing testPdfUploadCreatesThumbnail to fail. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is 🚀 New features to boost your workflow:
|
Summary
finallyblock)Root cause
When
readImageFile()is called with an anonymous stream, Ghostscript receives no filename or format hint and cannot seek backward. Modern PDFs commonly require non-linear reads to resolve cross-reference tables and compressed object streams, so any such PDF fails silently.Test plan
testPdfUploadCreatesThumbnail()toPhotosAddHandlerImagickTest— uploads a PDF and asserts a 200×200 thumb is producedSummary by CodeRabbit
Bug Fixes
Tests
Documentation
Chores