How to Set S3 ContentType and Other Request Headers with Laravel Filesystem / Cloud Storage

Laravel 5 brought to the table a powerful Storage Facade that allowed developers to easily integrate any kind of storage system into an application.

Amazon S3, being a Laravel native supported Filesystem, makes it easy to upload large files directly from the application to cheap and reliable storage.

S3 supports many types of request headers when making PUT requests, the one I was specifically interested in was ContentType.

The application was uploading an audio file, the ContentType of which is audio/mpeg. The default configuration was uploading the file as octet/stream. This would cause a browser to download the file, whereas we needed the ability to play the file directly from the browser.

The solution, albeit undocumented, is pretty simple.

Let’s assume you have an MP3 file, test.mp3 that you want to upload a public file that a user can play by simply visiting a url in the browser.


$test_mp3_path = '/path/to/test.mp3';

// Return MIME type ala mimetype extension
$finfo = finfo_open(FILEINFO_MIME_TYPE); 

// Get the MIME type of the file
$file_mime = finfo_file($finfo, $test_mp3_path);
finfo_close($finfo);

$file_handle = fopen($test_mp3_path, 'r');

// Here is the magic. getDriver() allows us to over-ride the default request config
Storage::disk('s3')
    ->getDriver()
    ->put( 'test.mp3',
           $file_handle,
           [
               'visibility' => 'public',
               'ContentType' => $file_mime
           ]
          );

Any of the accepted S3 request headers can be sent along with the payload.