Laravel: Upload File and Hide Real URL for Secure Download under UUID

File uploads are one of the essential things in web apps these days. But secure download of these files is sometimes even more important. So how to store files securely so people wouldn’t have access to them or guess their URLs or IDs of their records? Here’s a small demo tutorial.

What we’re building here

A small list of books with their covers, looks like this:

Looks simple, right? Now, let’s add some conditions:

  • Original cover filename should be visible but file can’t be accessed in public directly
  • You can download book cover with URL with book ID as a parameter, but that ID cannot be “guessable”

Preparation: structure

We will deal with only one DB table.
This is how our database migration looks like:

Field uuid will be used to hide original ID, and field cover will store the original filename.

Model app/Book.php is really simple – only fillable fields:

Now, we need two routes in routes/web.php:

So we manage books with resourceful BookController and will have a separate route for download.
The first part of controller looks simple – list and create form:

This is how our views look like – just a simple table and form.


And resources/views/books/create.blade.php:

Notice: our main resources/views/layouts/app.blade.php file is generated with php artisan make:auth command, we’re just reusing the same structure as default Laravel login/register pages.

This is how simple is the upload form:

Uploading the file

I have written a big big guide about uploading files in Laravel, but for this tutorial you need to know only a few things:

1. Upload form should contain <form enctype=”multipart/form-data”> – I’m shocked how many people forget this.

2. Upload app/Http/BookController.php code will look like this:

What we’re doing here:

  • We build the array $book which then is passed to Book::create() method;
  • We generate a unique UUID for the book with the help of webpatser/laravel-uuid package;
  • We check if there is a file, if so – we upload it to a storage/app/books folder with original filename (actual folder may depend on your config/filesystems.php settings);
  • Finally we redirect back to the list.

As a result, here’s what file will be uploaded and in which folder:

And here’s our database entry:

By default, file is stored in storage/app folder and not accessible to the public (unless you choose public driver), so that’s good – we achieve our first goal of securing the file.

But the second part – how to download the file without ability to guess its filename or ID?

Downloading File by its UUID

We already have this route:

In our Blade file, we refer to this route with this syntax:

So, this is how the actual URL looks like:

Finally, this is how download method looks like in app/Http/Controllers/BookController.php:

That’s it, users can download the file with its original filename, but without knowing where it is stored on the server, or book ID.

Hope that was helpful!

Want to generate Laravel adminpanel online?
You don't need any packages to do that!

5 thoughts on “Laravel: Upload File and Hide Real URL for Secure Download under UUID

  1. Why you don’t use the UUID as the file name for storing it ? If two files with the same name are uploaded, the second one will destroy the previous one.
    Many thanks for your briliant posts and videos.

    1. Good point, Gilles, this article indeed doesn’t cover that case.
      Or, probably, we should store files in their UUID folders, leaving original name. That depends on your implementation.

      Thanks for the comment!

Leave a Reply

Your email address will not be published. Required fields are marked *