Spark & Storage

I’ve been wanting to start blogging more frequent development updates and now is a great time to start!

This week I added profile photo upload / management to Spark. Adding this feature forced me to dig into Laravel’s Flysystem integration and file upload classes a little bit more than I have in the past, since both Forge and Envoyer do not accept any uploads.

One process I simplified is retrieving the URL for a file that has been publicly stored in the Flysystem. For the AWS adapter, this is a fairly simple task since the AWS SDK exposes a method to retrieve the URL.

However, for the local adapter, we have not had any convention for where user uploads should be stored. Furthermore, storing user uploads inside the public directory does not play nicely with zero downtime deployment solutions like Envoyer.

When using deployment systems like Envoyer, an entirely fresh copy of the repository is installed with each deploy and the storage directory is attached to a permanent storage directory using a symbolic link. If you store your user uploads in public, they will all go missing on your subsequent deployment. The solution is to store the uploads in your persistent storage directory and then create a symbolic link from your public directory to your storage directory during your deployment process.

Before yesterday, there was no conventional place to store these user uploads other than “anywhere you want within the storage directory”. After reviewing a few libraries in other languages, it became apparent that there would be great benefit to designating a standard location within the storage directory for files intended to be publicly accessible. So, I created the storage/app/public directory in the Laravel repository so that it will be present on all future installs of Laravel 5.2.

Having a standard location within storage for publicly accessible files allows package developers and service maintainers to make your life convenient. For example, in Envoyer, I plan to soon add an automatic hook to create a symbolic link from public/storage to storage/app/public without any manual configuration from users. This will make it a breeze to share user uploads across deployments without remembering to configure a custom deployment hook to build symbolic links.

I have also updated the default filesystems.php configuration file to include a public disk which stores files relative to storage/app/public so that you can easily start storing your files with simple, expressive syntax:

Storage::disk('public')->put($file, $contents);

I hope this will make your Laravel development life a little easier!