PHPnews.io

Convert and store Base64 encoded files in Laravel, use Validation rules, and access the decoded files from the Request…

Written by Pascal Baljet Media - Blog / Original link on Sep. 28, 2020

Laravel makes it easy to handle file uploads from a request that's multipart/form-data encoded. You can access uploaded files through a Request instance, and it has helper methods to store files easily. It also has a bunch of rules to validate incoming files. For example, you can verify that the incoming file is an image or matches a MIME type. It even has a convenient rule to validate that the image meets specific dimension constraints.

But what if the input is a base64 encoded string? You might want to upload files from an Android or iOS app that you're developing. Or maybe you're using a JavaScript library to process an image, like cropping, and you want to send the base64 string to your API. You could use the base64_decode() method and handle the storage from thereon in your controller. Managing the conversion in your controller takes away the ease of Form Request and the file-related methods of the Request object.

Recently I released a small package called Laravel Mixins. It's a set of little helpers for your Laravel application, but every feature is opt-in. This package has a trait that you can add to a Form Request to convert base64 input data to files. Let's take a look at a Form Request that we use to store an image.

use Illuminate\Foundation\Http\FormRequest;

class UploadAvatarRequest extends FormRequest
{
    public function rules()
    {
        return [
            'avatar' => ['required', 'file', 'image'],
        ];
    }
}

To use the trait, you need at least Laravel 6.0 and PHP 7.4 or higher. Let's install it using composer.

composer require protonemedia/laravel-mixins

Now we can add the ConvertsBase64ToFiles trait to the Form Request. The only thing left to do is adding a base64FileKeys() method to specify which input keys the trait should convert. You should return a simple key-value array. The key matches the input key, and the value is the desired filename since base64 encoded strings only includes the file contents.

use Illuminate\Foundation\Http\FormRequest;
use ProtoneMedia\LaravelMixins\Request\ConvertsBase64ToFiles;

class UploadAvatarRequest extends FormRequest
{
    use ConvertsBase64ToFiles;

    protected function base64FileKeys(): array
    {
        return [
            'avatar' => 'avatar_cropped.jpg',
        ];
    }

    public function rules()
    {
        return [
            'avatar' => ['required', 'file', 'image'],
        ];
    }
}

When you're using the Form Request in your controller, now the base64 encoded data gets validated as well! Calling the file method on the $request instance will give you an UploadedFile instance, just like a file that was uploaded using a multipart/form-data encoded form.

public function store(UploadAvatarRequest $request)
{
    // instance of Illuminate\Http\UploadedFile
    $avatarFile = $request->file('avatar');

    // avatar_cropped.jpg
    $avatarFile->getClientOriginalName(); 

    $path = $request->avatar->store('avatars', 's3');
}

This is just one of the features of the package. It also has Blade Directives, String macros, Validation rules, and other little components. You can find the documentation at the GitHub repository.

pascalbaljetmedia

« A rare look into the decision making process of a large project - Scout APM: Spend Less Time Troubleshooting, More Time Coding (sponsor) »