Last active
February 25, 2024 09:34
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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