Skip to content

Instantly share code, notes, and snippets.

@goran-popovic
Last active February 25, 2024 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goran-popovic/d5af7366af2a7f6f9b04ebc4a48a4e7e to your computer and use it in GitHub Desktop.
Save goran-popovic/d5af7366af2a7f6f9b04ebc4a48a4e7e to your computer and use it in GitHub Desktop.
Send, validate, and store Base64 files with Laravel - Basic Example (https://geoligard.com/send-validate-and-store-base64-files-with-laravel)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\File;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class Base64Controller extends Controller
{
public function index()
{
if (request()->isJson() && !empty(request()->input('image'))) {
$base64Image = request()->input('image');
if (!$tmpFileObject = $this->validateBase64($base64Image, ['png', 'jpg', 'jpeg', 'gif'])) {
return response()->json([
'error' => 'Invalid image format.'
], 415);
}
$storedFilePath = $this->storeFile($tmpFileObject);
if(!$storedFilePath) {
return response()->json([
'error' => 'Something went wrong, the file was not stored.'
], 500);
}
return response()->json([
'image_url' => url(Storage::url($storedFilePath)),
]);
}
return response()->json([
'error' => 'Invalid request.'
], 400);
}
/**
* Validate base64 content.
*
* @see https://stackoverflow.com/a/52914093
*/
private function validateBase64(string $base64data, array $allowedMimeTypes)
{
// strip out data URI scheme information (see RFC 2397)
if (str_contains($base64data, ';base64')) {
list(, $base64data) = explode(';', $base64data);
list(, $base64data) = explode(',', $base64data);
}
// strict mode filters for non-base64 alphabet characters
if (base64_decode($base64data, true) === false) {
return false;
}
// decoding and then re-encoding should not change the data
if (base64_encode(base64_decode($base64data)) !== $base64data) {
return false;
}
$fileBinaryData = base64_decode($base64data);
// temporarily store the decoded data on the filesystem to be able to use it later on
$tmpFileName = tempnam(sys_get_temp_dir(), 'medialibrary');
file_put_contents($tmpFileName, $fileBinaryData);
$tmpFileObject = new File($tmpFileName);
// guard against invalid mime types
$allowedMimeTypes = Arr::flatten($allowedMimeTypes);
// if there are no allowed mime types, then any type should be ok
if (empty($allowedMimeTypes)) {
return $tmpFileObject;
}
// Check the mime types
$validation = Validator::make(
['file' => $tmpFileObject],
['file' => 'mimes:' . implode(',', $allowedMimeTypes)]
);
if($validation->fails()) {
return false;
}
return $tmpFileObject;
}
/**
* Store the temporary file object
*/
private function storeFile(File $tmpFileObject)
{
$tmpFileObjectPathName = $tmpFileObject->getPathname();
$file = new UploadedFile(
$tmpFileObjectPathName,
$tmpFileObject->getFilename(),
$tmpFileObject->getMimeType(),
0,
true
);
$storedFile = $file->store('images/base64', ['disk' => 'public']);
unlink($tmpFileObjectPathName); // delete temp file
return $storedFile;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment