|
<?php |
|
|
|
namespace App\Support\Request; |
|
|
|
use Illuminate\Http\Testing\MimeType; |
|
use Illuminate\Support\Str; |
|
use Illuminate\Support\Arr; |
|
use Illuminate\Validation\Validator ; |
|
use Symfony\Component\HttpFoundation\File\UploadedFile; |
|
|
|
trait Base64AsBinary |
|
{ |
|
/** |
|
* If the attributes values is base64 data URI the cast to binary files |
|
* Then you can handle in laravel as a binare uploaded file |
|
* |
|
* Example in request: |
|
* ``` |
|
* protected function withValidator($validator) |
|
* { |
|
* $this->castBase64ToUploadedFile($validator, $attrs = ['logo']); |
|
* } |
|
* ``` |
|
* |
|
* @param Validator $validator |
|
* @param string|array $attributes - attribute name (as string, or array of strings) |
|
* @return void |
|
*/ |
|
public function castBase64ToUploadedFile(Validator $validator, $attributes) |
|
{ |
|
$data = $validator->getData(); |
|
foreach (Arr::wrap($attributes) as $attr) { |
|
$value = Arr::get($data, $attr); |
|
if (!$value) { |
|
continue; |
|
} |
|
|
|
if ($value instanceof UploadedFile) { |
|
// no nothing |
|
} |
|
|
|
// cast base64 to UploadedFile |
|
elseif ( |
|
is_string($value) |
|
&& $this->isBase64($value) |
|
) { |
|
$file = $this->mediaFromBase64($value); |
|
$data[$attr] = $file; |
|
$this->request->remove($attr); |
|
$this->files->set($attr, $file); |
|
} |
|
} |
|
|
|
// refresh convertedFiles Cache |
|
if (array_keys($this->files->all()) !== array_keys($this->allFiles())) { |
|
$this->convertedFiles = $this->convertUploadedFiles( |
|
$this->files->all() |
|
); |
|
} |
|
|
|
$validator->setData($data); |
|
} |
|
|
|
/** |
|
* Validate base64 data uri according to RFC 2397 with regex pattern |
|
* |
|
* @param string $base64 |
|
* @return boolean |
|
*/ |
|
private function isBase64(string $base64): bool |
|
{ |
|
/** |
|
* @link https://gist.github.com/khanzadimahdi/bab8a3416bdb764b9eda5b38b35735b8 |
|
*/ |
|
$re = '/^data:((?:\w+\/(?:(?!;).)+)?)((?:;[\w\W]*?[^;])*),(.+)$/'; |
|
|
|
return Str::matchAll($re, $base64)->isNotEmpty(); |
|
} |
|
|
|
/** |
|
* Create `UploadedFile` instance From base64 data URI |
|
* |
|
* @param string $base64data |
|
* @return UploadedFile |
|
*/ |
|
private function mediaFromBase64(string $base64data): UploadedFile |
|
{ |
|
// strip out data uri scheme information (see RFC 2397) |
|
if (strpos($base64data, ';base64') !== false) { |
|
[$dataMime, $base64data] = explode(';', $base64data); |
|
[$_, $base64data] = explode(',', $base64data); |
|
[$_, $mimeType] = explode(':', $dataMime); |
|
} |
|
|
|
// strict mode filters for non-base64 alphabet characters |
|
$binaryData = base64_decode($base64data, true); |
|
|
|
// temporarily store the decoded data on the filesystem to be able to pass it to the fileAdder |
|
$tmpFile = tempnam(sys_get_temp_dir(), 'file'); |
|
file_put_contents($tmpFile, $binaryData); |
|
|
|
// filename with extension |
|
$filename = 'file.' . MimeType::search($mimeType); |
|
|
|
|
|
$file = new UploadedFile( |
|
$tmpFile, |
|
$filename, |
|
$mimeType, |
|
|
|
/** |
|
* IMPORTANT TO KNOW |
|
* The following paramters avoid `is_uploaded_file` validation. |
|
* Be sure that is validation mime types and other validation rules to be safe |
|
* @link https://www.php.net/manual/pt_BR/function.is-uploaded-file.php |
|
*/ |
|
$error = UPLOAD_ERR_OK, |
|
$test = true |
|
); |
|
|
|
return $file; |
|
} |
|
} |