Skip to main content

Laravel File Handling

The thing I like best about Laravel is its elegance.  As far as I'm concerned, it is the cleanest framework out there, even with its limitations.  So I just had to write this post about how I handle files in Laravel.  Note that the storage path can be configured to local storage or to an S3 bucket.

First, we need a route for opening the file in our routes.php file:

// Open a file
Route::get('file/{id}', 'HomeController@getFile');

Then, in our home controller, the related function:

/** * Open file
*/
public function getFile($filename)
{
// Full path
$path = storage_path('app/' . $filename);

// Determine the mime type
$mimetype = mime_content_type($path);

// Return the file
return response()->file($path, ['Content-Type: ' . $mimetype . '; charset=utf-8']);
}



That's it!  When you hit that URL route, the file will automatically open.

If you aren't sure whether your environment supports the mime_content_type() function, you can add a little bit of extra code (this part comes from php.net):


/**
* Open a file
*/
public function getFile($filename)
{
// Full path
$path = storage_path('app/' . $filename);

// Determine the mime type
if (function_exists('mime_content_type')) {
$mimetype = mime_content_type($path);
} else {
$mime_types = [
'txt' => 'text/plain',
'htm' => 'text/html',
'html' => 'text/html',
'php' => 'text/html',
'css' => 'text/css',
'js' => 'application/javascript',
'json' => 'application/json',
'xml' => 'application/xml',
'swf' => 'application/x-shockwave-flash',
'flv' => 'video/x-flv',
// images
'png' => 'image/png',
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'ico' => 'image/vnd.microsoft.icon',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'svg' => 'image/svg+xml',
'svgz' => 'image/svg+xml',
// archives
'zip' => 'application/zip',
'rar' => 'application/x-rar-compressed',
'exe' => 'application/x-msdownload',
'msi' => 'application/x-msdownload',
'cab' => 'application/vnd.ms-cab-compressed',
// audio/video
'mp3' => 'audio/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
// adobe
'pdf' => 'application/pdf',
'psd' => 'image/vnd.adobe.photoshop',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
// ms office
'doc' => 'application/msword',
'docx' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'pptx' => 'application/vnd.ms-powerpoint',
'rtf' => 'application/rtf',
// open office
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
];

// Get extension
$ext = strtolower(array_pop(explode('.', $filename)));

// Match to mime type
if (array_key_exists($ext, $mime_types)) {
$mimetype = $mime_types[$ext];
} else {
$mimetype = 'application/octet-stream';
}
}

// Return the file
return response()->file($path, ['Content-Type: ' . $mimetype . '; charset=utf-8']);
}

Comments

Popular posts from this blog

jQuery noUIslider Pip Label Customization

Recently, I was tasked with creating a slider element for a user to select their credit rating, of which the user can select from among: 'Poor', 'Fair', 'Good', 'Excellent' and 'Not Sure'.  Several problems presented themselves here: A drop-down box would be better, but that's not what the requirements specified. I already have several numeric sliders on my page and I want them all to match. I selected the jQuery noUi Slider library to create the numeric sliders. noUi Slider does not support string values - only numeric values. The "pips" (slider scale/labels) also does not support string values. Since the solution involved shifting my mindset, I wanted to document it here for future reference and maybe to help someone facing the same requirements. Here's my solution: Since there is really no numeric correlation to credit score (especially considering one of the options is "Not Sure"), I will just u...

Salesforce Apex: Replacing and/or Removing Apex Classes

Working with code within the constraints of Salesforce's workflow can be a challenge.  First , you have the restriction on changing anything in production.  Second , you have the requirement for 75% or greater unit test coverage.  Third , you have the fact that certain metadata cannot be pushed to production through a changeset (which means the only way to sync record IDs is by re-deploying the development environment from production). Fourth - and this is what I'd like to blog about today - you cannot delete classes from production through the Salesforce UI .  The only way to delete a class from production is to download the class (and its associated metadata file) into the Eclipse IDE (which you have previously set up with the Apex add-on), change the "status" flag to "Deleted", then deploy the changed metadata file to production.  And (here's the kicker)...sometimes it doesn't work because...reasons. So let's start with the workflow of a f...

More Laravel Magic - Touches

What is "touches"?  Well, anyone familiar with Linux/Unix is going to be familiar with the concept of "touching" a file.  Touching a file sets the "last modified" timestamp (or creates the file if it doesn't exist).  Knowing when a file was last modified can be very important for version control. Laravel has something similar for its model relations.  For example, lets say there is a club with many members.  When a member joins, leaves or gets a new role in the club, you might contend that the club has changed.  In terms of Laravel, you would want the club table's "updated_at" timestamp to reflect that change.  Enter the "touches" property... To make the magic happen in Laravel, you simply need to define the parent relationship and add it to the touches property like so: <?php class Club extends Model { /** * Touches (touch parent model when this model changes) */ protected $touches = [ ...