Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rublopweb's avatar

Uploading files to S3 and adding to Media

Hi everyone, I am working on a project in which i have to upload some files to a specific path in S3 and associate that file to an eloquent model using the media spatie library. What i have done is create a job that is dispatched when the model is created, that uploads the file to s3 and add it to the media table.

My model looks like this:

class Document extends Model implements HasMedia{
 	
	use InteractsWithMedia;

	    protected static function booted()
    {   
        static::created(function (Document $document) {
            GenerateDocumentPdfJob::dispatch($document)->onQueue('documentsDrafts');
        });
    }
      /**
     * @return string
     */
    public function render()
    {   
        return PDF::loadView('htmlToPdf.document', ['document' => $this])->output();
    }
}

The job class is this one:

class GenerateDocumentPdfJob implements ShouldQueue

	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected Document $document;

     /**
     * Create a new job instance.
     *
     * @param Document $document
     */
    public function __construct(Document $document)
    {
        $this->document = $document;
    }

    public function handle()
    {       
            $folders = ['Douments', $this->document->year];
            $filename = sprintf('Document%s.pdf', $this->document->id);
            $document = $this->document;

            S3PathHelper::UploaDocumentlToS3($document, $filename, $folders);
    }

And the function of the S3PathHelper is this one:

    public static function UploaDocumentlToS3(Docment $document, string $file_name, array $folders)
    {

        $path = implode('/', $folders) . '/' . $file_name;
        $pdfContent = $document->render();
        try {

            Storage::disk('s3')->put($path, $pdfContent);
            $document->addMediaFromDisk($path, 's3')->toMediaCollection('documents');
        } catch (S3Exception $ex) {
            throw new Exception('Error UploaDocumentlToS3 function.', $ex->getMessage());
        }
    }

I would like to know if this is a valid code for the goal i want and if there are any issues that could happen? Thanks a lot,

0 likes
1 reply
LaryAI's avatar
Level 58

Hello,

Your approach to uploading files to S3 and associating them with an Eloquent model using the Spatie Media Library seems to be on the right track. However, there are a few points that you might want to consider:

  1. Typo in the method name: It seems there is a typo in the method name UploaDocumentlToS3. It should be UploadDocumentToS3.

  2. Exception handling: You are catching an S3Exception, but it's not clear if this exception is imported or if it's the correct exception class that the AWS SDK throws. You should make sure you are catching the correct exception type. The AWS SDK for PHP throws Aws\S3\Exception\S3Exception.

  3. Error handling in the job: If the upload or media association fails, you are throwing an exception. You should ensure that your job is set up to handle retries or failures as needed.

  4. Temporary files: When using addMediaFromDisk, the Spatie Media Library expects the file to be on a local disk. Since you are uploading directly to S3, you might need to download the file temporarily to the local disk before running addMediaFromDisk.

  5. File visibility: Ensure that the file visibility on S3 is set correctly, whether it's public or private, depending on your application's needs.

  6. Job dispatching: You are dispatching the job in the booted method of the model. Make sure that this is the best place for it, as it will run every time a Document is created, which might not always be when you want to generate and upload the PDF.

Here's a revised version of your S3PathHelper function with some of these considerations:

use Illuminate\Support\Facades\Storage;
use Aws\S3\Exception\S3Exception;

class S3PathHelper
{
    public static function UploadDocumentToS3(Document $document, string $file_name, array $folders)
    {
        $path = implode('/', $folders) . '/' . $file_name;
        $pdfContent = $document->render();

        try {
            // Upload the PDF content directly to S3
            Storage::disk('s3')->put($path, $pdfContent, 'public');

            // Assuming the file needs to be public, otherwise remove the 'public' parameter

            // Download the file to a temporary location
            $temporaryPath = tempnam(sys_get_temp_dir(), 'media');
            Storage::disk('s3')->getDriver()->getObject([
                'Bucket' => config('filesystems.disks.s3.bucket'),
                'Key'    => $path,
                'SaveAs' => $temporaryPath,
            ]);

            // Add the media from the temporary file to the media collection
            $document->addMedia($temporaryPath)
                     ->toMediaCollection('documents');

            // Delete the temporary file
            unlink($temporaryPath);
        } catch (S3Exception $ex) {
            // Handle the exception properly
            throw new Exception('Error uploading document to S3.', 0, $ex);
        }
    }
}

Please note that this code assumes that you have the AWS SDK for PHP installed and configured correctly, and that you have set up your filesystems.php config file with the correct S3 disk configuration.

Remember to test this thoroughly in a development environment before deploying to production.

Please or to participate in this conversation.