Merge pull request #18003 from uberbrady/fix_file_upload_base64

Fixed [FD-50921] - base64-encoded image files for asset creation was broken
This commit is contained in:
snipe
2025-10-07 17:34:53 +01:00
committed by GitHub
3 changed files with 31 additions and 10 deletions

View File

@@ -26,6 +26,7 @@ class StoreAssetRequest extends ImageUploadRequest
public function prepareForValidation(): void
{
parent::prepareForValidation(); // call ImageUploadRequest thing
// Guard against users passing in an array for company_id instead of an integer.
// If the company_id is not an integer then we simply use what was
// provided to be caught by model level validation later.

View File

@@ -2,6 +2,7 @@
namespace App\Http\Traits;
use Illuminate\Validation\ValidationException;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
@@ -38,20 +39,13 @@ trait ConvertsBase64ToFiles
if (!$base64Contents) {
return;
}
// autogenerate filenames
if ($filename == 'auto'){
$header = explode(';', $base64Contents, 2)[0];
// Grab the image type from the header while we're at it.
$filename = $key . '.' . substr($header, strpos($header, '/')+1);
}
// Generate a temporary path to store the Base64 contents
$tempFilePath = tempnam(sys_get_temp_dir(), $filename);
// Store the contents using a stream, or by decoding manually
// Store the contents using a stream, or throw an Error (which doesn't do anything?)
if (Str::startsWith($base64Contents, 'data:') && count(explode(',', $base64Contents)) > 1) {
$source = fopen($base64Contents, 'r');
$source = fopen($base64Contents, 'r'); // PHP has special processing for "data:" URL's
$destination = fopen($tempFilePath, 'w');
stream_copy_to_stream($source, $destination);
@@ -59,7 +53,8 @@ trait ConvertsBase64ToFiles
fclose($source);
fclose($destination);
} else {
file_put_contents($tempFilePath, base64_decode($base64Contents, true));
// TODO - to get a better error message here, can we maybe do something with modifying the errorBag?
throw new ValidationException("Need Base64 URL starting with 'data:'"); // This doesn't actually throw?
}
$uploadedFile = new UploadedFile($tempFilePath, $filename, null, null, true);

View File

@@ -11,6 +11,7 @@ use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\User;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Storage;
use Illuminate\Testing\Fluent\AssertableJson;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;
@@ -831,4 +832,28 @@ class StoreAssetTest extends TestCase
$asset = Asset::findOrFail($response['payload']['id']);
$this->assertEquals('This is encrypted field', Crypt::decrypt($asset->{$field->db_column_name()}));
}
public function testBase64AssetImages()
{
$status = Statuslabel::factory()->readyToDeploy()->create();
$model = AssetModel::factory()->create();
$superuser = User::factory()->superuser()->create();
$response = $this->actingAsForApi($superuser)
->postJson(route('api.assets.store'), [
'model_id' => $model->id,
'status_id' => $status->id,
'asset_tag' => '1234',
'image' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsAQMAAADXeXeBAAAABlBMVEX+AAD///+KQee0AAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH5QQbCAoNcoiTQAAAACZJREFUaN7twTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAICnATvEAAEnf54JAAAAAElFTkSuQmCC'
])
->assertStatusMessageIs('success')
->assertOk()
->json();
$asset = Asset::findOrFail($response['payload']['id']);
$this->assertEquals($asset->asset_tag, '1234');
$image_data = Storage::disk('public')->get(app('assets_upload_path') . e($asset->image));
//$this->assertEquals('3d67fb99a0b6926e350f7b71397525d7a6b936c1', sha1($image_data)); //this doesn't work because the image gets resized - use the resized hash instead
$this->assertEquals('db2e13ba04318c99058ca429d67777322f48566b', sha1($image_data));
}
}