30 December 2018 · Technology Laravel Redis

Use Redis instead of local storage for file uploads with Laravel

This story is about how to make Redis as your default caching engine and use it as a temporary file storage instead of local storage folder on your server.

This story assumes that you have a basic knowledge of PHP, Laravel. If you don't have these basic knowledge there are tons of articles and tutorials that explains PHP and Laravel Framework.
You could take a look on PHP and  Laravel documentations as they are really simple and straightforward.  
Also I assume that you have Redis installed on your local machine, If you didn't install it yet, please take a look on this article from Redis official documentation on how to install Redis on Ubuntu, I followed the same tutorial with Ubuntu 18.04 and it's working just fine.

So, Let me specify why we thought about this approach for such a simple task as a "File upload"

multiple_instances

But what if one or more of these instances are down while someone already uploaded his file to it's local storage?!
in that case this file won't be available when the othe instance is up and running.

So the proper structure would be:
- A server and it's multiple instances for example: AWS EC2 to increase availability.
- A server for Redis engine as a database, cache and message broker.
- Cloud storage for uploaded file such as AWS S3.


Let's take a look at the implementation:

php artisan make:model UploadImage -m -cr

- One to return the upload form view
- The other one is to call the update method in the controller

Navigate to routes/web.php and add these routes:

Route::get('/upload/image', 'UploadImageController@index')->name('home');
Route::post('/upload/image', 'UploadImageController@update')->name('update');
    public function index()
    {
        return view('uploadImage');
    }
public function update(Request $request)
  {
    $file_base46 = base64_encode(file_get_contents($request->file('image')->getPathname()));
    $fileName = $request->file('image')->getFilename();
    Cache::store('redis')->put($fileName, $file_base46, 10);
    return redirect()->back()
        ->with('message', 'your file is uploaded successfully!')
        ->with('redis_key', $fileName);
  }
@if (session()->has('message'))
  <div class="alert alert-success" role="alert">
  {{ session()->get('message') }}
  <a href="/view/image/{{session()->get('redis_key')}}" target="_blank">Here</a>
  </div>
  @endif
  {{ Form::open(array('url' =>'upload/image','files'=>'true')) }}
  {{ Form::file('image') }}
  {{ Form::submit('Upload File')}}
  {{ Form::close() }}
public function showImage($redisKey){
    $base46Image = Cache::get($redisKey);
    return view('uploadedImage')->with('image_src',$base46Image);
}
Route::get('/view/image/{redisKey}', 'UploadImageController@showImage')->name('show');
Route::get('/view/image', 'UploadImageController@showImage')->name('show');
<img src="data:image/png;base64 , {{$image_src}}" alt="img">

At the end, I believe that this approach will achieve the high availability with out risking using data. But for any other suggestions, feedback or questions please let me know by contacting me.
And if you new to Redis, I'd like to recommend this website as it will really help you to start getting to know it.