Laravel使用FPDF编辑S3中PDF遇流不可寻错误的解决问询
Got it, I’ve run into this exact issue before with PDF libraries like FPDI/TCPDF and S3-hosted files—let’s break down why it’s happening and how to fix it.
The core problem here is that remote S3 URLs return streams that aren’t seekable. PDF editing libraries need to jump around (seek) within the file to parse different sections, but S3’s remote streams don’t support this by default. Even though you can fetch the content and send it to the frontend, that’s a one-way read operation that doesn’t require seeking.
Luckily, there’s a straightforward workaround: grab the PDF content from S3, save it to a local temporary file, and then pass that temporary file path to setSourceFile(). Here’s how to implement it:
Step-by-Step Solution
1. Fetch the PDF content from S3
Use Laravel’s Storage facade to pull the raw content of your PDF from the S3 disk.
2. Create a local temporary file
Save the S3 content to a temporary file on your server—this gives you a fully seekable stream that the PDF library can work with.
3. Clean up after editing
Make sure to delete the temporary file once you’re done to avoid cluttering your server’s disk space.
Here’s the full code example:
use Illuminate\Support\Facades\Storage; // Fetch the raw PDF content from your S3 disk $pdfContent = Storage::disk(env('FILESYSTEM'))->get($url); // Create a unique temporary file (uses your server's default temp directory) $tempFilePath = tempnam(sys_get_temp_dir(), 'laravel_s3_pdf_'); // Write the S3 PDF content to the temporary file file_put_contents($tempFilePath, $pdfContent); try { // Now pass the temporary file path to setSourceFile() $pdf->setSourceFile($tempFilePath); // ... Add your PDF editing logic here (import pages, modify content, etc.) ... } finally { // Always clean up the temporary file, even if an error occurs during editing if (file_exists($tempFilePath)) { unlink($tempFilePath); } }
Alternative: Stream-Based Approach
If you prefer working with streams instead of writing to a physical file, you can copy the S3 stream to a seekable temporary stream (like php://temp). However, most PDF libraries still expect a file path for setSourceFile(), so the temporary file method is more reliable. That said, here’s a snippet for reference:
$remoteStream = Storage::disk(env('FILESYSTEM'))->readStream($url); $seekableStream = fopen('php://temp', 'w+b'); // Copy the remote S3 stream to the seekable temporary stream stream_copy_to_stream($remoteStream, $seekableStream); rewind($seekableStream); // Note: Check your PDF library's docs to see if it accepts a stream directly // Most require a file path, so you'd still need to save this stream to a temp file
Why This Works
Local files on your server have fully seekable streams—your PDF library can jump forward and backward in the file as needed, which eliminates the "Given stream is not seekable!" error. The finally block ensures the temporary file is deleted no matter what, so you don’t have to worry about leftover files taking up space.
内容的提问来源于stack exchange,提问作者Javier Young

